Note
Written by claude-opus-5-5 via Claude Code on behalf of Matt.
This was generated by AI during triage.
Triage: bug, marked evidence-affecting, and kept in needs-triage so it can be folded into the capture engine design work.
I reproduced the defect, and it is broader than the issue states. When the app saves a page, the browser's saver drops the list of alternative image sources from every image. An image offered only through that list is missing from the saved page even though the browser fetched and displayed it. An image that also has a plain source is worse: the saved page stores the bytes of the image the page displayed under the plain source's address, which the browser never requested, so the saved page names the wrong origin for those bytes. Images inside a picture element and plain images save correctly. This is how the browser saver behaves every time, not a one-off result.
The browser extension saves pages through the same browser feature, so it probably behaves the same way, but I did not test it.
The three fixes I can see all need a decision about how evidence is handled: rewrite the page before saving it, record the gap as a stated limitation of the saved page, or rely on the planned transaction record for the true bytes. I have not picked one.
The test page, the run, and what the saved file held
Run on 2026-10-14 against origin/main 0c5ee8fc's Electron 44.7.0 (Chromium 152.0.7977.130), under xvfb-run on Linux. A standalone Electron script served this page from 127.0.0.1, loaded it in a hidden BrowserWindow, waited 1.5 s, and called webContents.savePage(path, 'MHTML'), the same call backgroundRenderer.ts makes. Each image response was a 1x1 PNG with TAG:<request path> appended after IEND, so the bytes in each MHTML part name the request that served them.
| 1 | <img srcset="/srcset-only-1x.png 1x, /srcset-only-2x.png 2x" width="10" height="10"> |
| 2 | <img src="/src-fallback.png" srcset="/srcset-with-src-1x.png 1x, /srcset-with-src-2x.png 2x" width="10" height="10"> |
| 3 | <img srcset="/srcset-w-400.png 400w, /srcset-w-800.png 800w" sizes="10px" width="10" height="10"> |
| 4 | <picture><source srcset="/picture-source.png" type="image/png"><img src="/picture-fallback.png" width="10" height="10"></picture> |
| 5 | <img src="/plain.png" width="10" height="10"> |
| Image | Requested and shown (currentSrc) | In the MHTML | Saved <img> markup |
|---|---|---|---|
srcset only, x descriptors | /srcset-only-1x.png | no part | <img width height> |
src + srcset | /srcset-with-src-1x.png | part Content-Location: /src-fallback.png, bytes tagged /srcset-with-src-1x.png | src="/src-fallback.png", no srcset |
srcset only, w descriptors | /srcset-w-400.png | no part | <img width height> |
<picture> | /picture-source.png | part /picture-source.png, bytes match | <source srcset> kept |
plain src | /plain.png | part /plain.png, bytes match | unchanged |
The server log never shows a request for /src-fallback.png.
Call sites that use the Blink MHTML serializer: src/main/services/backgroundRenderer.ts (wc.savePage(tmpPath, 'MHTML')) and extension/src/background.ts (chrome.pageCapture.saveAsMHTML). The extension path was not run.
Related records: ADR-0004 already says MHTML is a browser representation and not a complete transaction record, and ADR-0035 puts a WARC transaction record beside the MHTML. Whether that record should be the answer for these bytes is part of the open decision.