[GH-ISSUE #5411] [Bug] A zero-byte raw/NN_s.txt (session with no response) makes inspect_web_network_capture reject the whole SAZ archive #3279

Closed
opened 2026-10-31 00:38:42 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @Rinkia on GitHub (Oct 20, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/5411

Before submitting

  • I searched the open and closed issues for a related report (SAZ empty member, header/body separator, x49_mp_cs21). The only mention is the experiment from #3132 (experiments/analysis-efficiency/saz-selection-workflows.md), which keeps x49_mp_cs21.saz as a negative probe for exactly this failure but makes no repair claim. I found no issue or PR for it.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Browser, web, or network capture

Observed behavior

Fiddler writes a zero-byte response member when a session never got a response. REA rejects the whole archive because of that one member:

{"code":"invalid_request","category":"invalid_input",
 "details":{"operation":"inspect_web_network_capture",
  "issues":[{"path":["capture_path",""],"reason":"invalid_format",
             "message":"SAZ HTTP message has no header/body separator."}]}}

Selecting other records (--record 0) fails the same way, so none of the other 102 sessions can be read.

The same session with its _s.txt missing works: the response is null, as the docs describe ("Missing members remain null, distinct from empty bodies"). Only the empty-file spelling of "no response" is rejected.

Input Result
clear_nomp.saz (13 sessions, unmodified) OK, 13 records
same, raw/05_s.txt removed OK, 13 records, records[4].reported.response = null
same, raw/05_s.txt kept as 0 bytes invalid_request / invalid_format, no records
x49_mp_cs21.saz (genuine Fiddler v4.6.2.26757 archive, 103 sessions) invalid_request / invalid_format, no records

The genuine case is session 099 of x49_mp_cs21.saz (SID 212). It is a POST http://…:5985/wsman/… whose _m.xml shows the request was received but no server connection was made: ServerConnected, GotResponseHeaders and ClientDoneResponse are all 0001-01-01T00:00:00, and it has x-dns-failover. raw/099_s.txt is 0 bytes; it is the only empty session member in the archive.

Source-derived on main 074768901: decodeSazHttp in src/browser/history/SazHttp.ts throws CaptureFormatError whenever neither \r\n\r\n nor \n\n is found, which a zero-byte buffer can never contain.

For comparison, Microsoft's Xbox Live Trace Analyzer, which ships this archive as test data, reads _s.txt line by line and tolerates an empty one (Source/RulesEngine/ServiceCallItem.cs, lines 421-442 at ad880ff0).

Reproduction

Public archive from Microsoft's Xbox Live Trace Analyzer at ad880ff00b26c4cae5e3c8864d3df438a03890ba (MIT), already pinned in REA's experiments/analysis-efficiency/corpus.json:

  • Source/TestData/CertWarnings/x49_mp_cs21.saz, 572,224 bytes, sha256 97cdca8b0608e3f11995fd64b64390b9fd8d8e3efcac89f517f24b44968047f6 (git blob e7794c44… matches)
rea inspect-web-network-capture /targets/x49_mp_cs21.saz saz --format json
rea inspect-web-network-capture /targets/x49_mp_cs21.saz saz --record 0 --format json

Minimal fixture: rewrite clear_nomp.saz from the same directory (sha256 3e808663…0375) with raw/05_s.txt set to zero bytes. I can attach it.

Expected behavior

Treat a zero-byte _c.txt/_s.txt as "no message recorded", like a missing member: a null request or response, the member still listed in location.members, and a per-record limitation saying the stored member was empty. The rest of the archive stays readable. If REA prefers to keep the distinction between empty and missing, a per-record issue with partial coverage would still be better than rejecting every session.

Impact and scope

Any SAZ that contains a session without a response (aborted, DNS failure, client disconnect, or a capture stopped mid-request) is completely unreadable. These are common in real proxy captures.

Tested on rea-agents@6.7.0 (Docker, Node 24.22.0): the two real archives and the two fixtures above. On the same build, the other two Xbox archives (13 and 1,311 sessions) match an independent zipfile reader on every session: start lines, ordered headers, all 2,622 body byte counts and SHA-256s, the 3 WebSocket members, and 1,125 credential headers redacted with no value leaked.

Originally created by @Rinkia on GitHub (Oct 20, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5411 ### Before submitting - [x] I searched the open and closed issues for a related report (SAZ empty member, header/body separator, x49_mp_cs21). The only mention is the experiment from #3132 (`experiments/analysis-efficiency/saz-selection-workflows.md`), which keeps `x49_mp_cs21.saz` as a negative probe for exactly this failure but makes no repair claim. I found no issue or PR for it. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Browser, web, or network capture ### Observed behavior Fiddler writes a zero-byte response member when a session never got a response. REA rejects the whole archive because of that one member: ```json {"code":"invalid_request","category":"invalid_input", "details":{"operation":"inspect_web_network_capture", "issues":[{"path":["capture_path",""],"reason":"invalid_format", "message":"SAZ HTTP message has no header/body separator."}]}} ``` Selecting other records (`--record 0`) fails the same way, so none of the other 102 sessions can be read. The same session with its `_s.txt` **missing** works: the response is `null`, as the docs describe ("Missing members remain null, distinct from empty bodies"). Only the empty-file spelling of "no response" is rejected. | Input | Result | |---|---| | `clear_nomp.saz` (13 sessions, unmodified) | OK, 13 records | | same, `raw/05_s.txt` removed | OK, 13 records, `records[4].reported.response = null` | | same, `raw/05_s.txt` kept as 0 bytes | `invalid_request` / `invalid_format`, no records | | `x49_mp_cs21.saz` (genuine Fiddler v4.6.2.26757 archive, 103 sessions) | `invalid_request` / `invalid_format`, no records | The genuine case is session 099 of `x49_mp_cs21.saz` (SID 212). It is a `POST http://…:5985/wsman/…` whose `_m.xml` shows the request was received but no server connection was made: `ServerConnected`, `GotResponseHeaders` and `ClientDoneResponse` are all `0001-01-01T00:00:00`, and it has `x-dns-failover`. `raw/099_s.txt` is 0 bytes; it is the only empty session member in the archive. Source-derived on `main` `074768901`: `decodeSazHttp` in `src/browser/history/SazHttp.ts` throws `CaptureFormatError` whenever neither `\r\n\r\n` nor `\n\n` is found, which a zero-byte buffer can never contain. For comparison, Microsoft's Xbox Live Trace Analyzer, which ships this archive as test data, reads `_s.txt` line by line and tolerates an empty one (`Source/RulesEngine/ServiceCallItem.cs`, lines 421-442 at `ad880ff0`). ### Reproduction Public archive from Microsoft's Xbox Live Trace Analyzer at `ad880ff00b26c4cae5e3c8864d3df438a03890ba` (MIT), already pinned in REA's `experiments/analysis-efficiency/corpus.json`: - `Source/TestData/CertWarnings/x49_mp_cs21.saz`, 572,224 bytes, sha256 `97cdca8b0608e3f11995fd64b64390b9fd8d8e3efcac89f517f24b44968047f6` (git blob `e7794c44…` matches) ```sh rea inspect-web-network-capture /targets/x49_mp_cs21.saz saz --format json rea inspect-web-network-capture /targets/x49_mp_cs21.saz saz --record 0 --format json ``` Minimal fixture: rewrite `clear_nomp.saz` from the same directory (sha256 `3e808663…0375`) with `raw/05_s.txt` set to zero bytes. I can attach it. ### Expected behavior Treat a zero-byte `_c.txt`/`_s.txt` as "no message recorded", like a missing member: a `null` request or response, the member still listed in `location.members`, and a per-record limitation saying the stored member was empty. The rest of the archive stays readable. If REA prefers to keep the distinction between empty and missing, a per-record issue with partial coverage would still be better than rejecting every session. ### Impact and scope Any SAZ that contains a session without a response (aborted, DNS failure, client disconnect, or a capture stopped mid-request) is completely unreadable. These are common in real proxy captures. Tested on `rea-agents@6.7.0` (Docker, Node 24.22.0): the two real archives and the two fixtures above. On the same build, the other two Xbox archives (13 and 1,311 sessions) match an independent `zipfile` reader on every session: start lines, ordered headers, all 2,622 body byte counts and SHA-256s, the 3 WebSocket members, and 1,125 credential headers redacted with no value leaked.
Author
Owner

@amyanger commented on GitHub (Oct 20, 2026):

I'm working on this. A draft fix is up in #5453: a zero-byte _c.txt or _s.txt member is reported as a null request or response with a per-record limitation, so the rest of the archive stays readable. I checked it against x49_mp_cs21.saz from the issue, and all 103 sessions now decode.

<!-- gh-comment-id:6289220547 --> @amyanger commented on GitHub (Oct 20, 2026): I'm working on this. A draft fix is up in #5453: a zero-byte `_c.txt` or `_s.txt` member is reported as a null request or response with a per-record limitation, so the rest of the archive stays readable. I checked it against `x49_mp_cs21.saz` from the issue, and all 103 sessions now decode.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3279
No description provided.