[GH-ISSUE #7293] [Bug] Pcap count contradictions lose their specific reason in the CLI error #4332

Closed
opened 2026-10-31 00:48:58 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 26, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/7293

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Process capture or runtime observation

Observed behavior

inspect-pcap-capture correctly refuses contradictory producer results, but its CLI error loses the known reason. In the executed case, the selected capinfos reports one packet while the selected TShark returns []. REA returns unreadable_output with no details property and tells the caller to review reported details. The provider constructs the specific reason capinfos counted 1 packets but tshark returned 0, but that reason is absent from the public result.

The zero-packet control succeeds with packet_count: 0 and coverage: "complete". These are controlled producer fixtures exercising the actual public CLI, Linux process/resource boundary, parsing and result projection; they do not establish real Wireshark behavior.

Reproduction

Run the following from a built REA checkout on Linux with Node 24.22.1, Python 3 and util-linux prlimit available. The script creates a 24-byte empty pcap header and controlled executable shell fixtures. Their --version responses pass the documented Wireshark 4.x admission; their capture responses deliberately differ only in the capinfos packet count. It isolates home, config, cache and temporary files, then removes the fixtures. One mismatch run and one control were independently executed as uid 1000 in a Debian bookworm Linux arm64 container with networking disabled and the checkout mounted read-only.

#!/bin/sh
set -eu
work="$(mktemp -d)"
trap 'rm -rf "$work"' EXIT
mkdir -p "$work/bin" "$work/home" "$work/config" "$work/cache" "$work/tmp"
python3 - "$work" <<'FIXTURE'
from pathlib import Path
import struct, sys
root = Path(sys.argv[1])
root.joinpath('capture.pcap').write_bytes(struct.pack('<IHHIIII', 0xa1b2c3d4, 2, 4, 0, 0, 65535, 1))
root.joinpath('bin/tshark').write_text("""#!/bin/sh
if [ "$1" = "--version" ]; then printf 'TShark (Wireshark) 4.6.6-stub\n'; exit 0; fi
printf '[]'
""")
for count in (0, 1):
    root.joinpath(f'bin/capinfos-{count}').write_text("""#!/bin/sh
if [ "$1" = "--version" ]; then printf 'Capinfos (Wireshark) 4.6.6-stub\n'; exit 0; fi
printf 'File type: pcap\nFile encapsulation: Ethernet\nNumber of packets: %s\n'
""" % count)
for tool in root.joinpath('bin').iterdir():
    tool.chmod(0o755)
FIXTURE
for count in 0 1; do
  printf '\ncapinfos_count=%s\n' "$count"
  set +e
  HOME="$work/home" XDG_CONFIG_HOME="$work/config" XDG_CACHE_HOME="$work/cache" TMPDIR="$work/tmp" REA_TSHARK_COMMAND="$work/bin/tshark" REA_CAPINFOS_COMMAND="$work/bin/capinfos-$count" node scripts/rea.mjs inspect-pcap-capture "$work/capture.pcap" --json
  status=$?
  set -e
  printf 'exit_status=%s\n' "$status"
done

Expected behavior

Keep refusing the contradictory producer results, while reporting the concrete packet-count disagreement in a caller-visible reason or diagnostic. The repository's AGENTS.md, Architecture and Cleanup, requires preserving meaningful failure reasons. The refusal should provide the detail its recovery advice tells the caller to review. This report does not require partial success or a different error code.

Impact and scope

Observed once in one controlled mismatch attempt, with one passing zero-packet control. The capture is correctly refused; the diagnostic does not tell the caller why. No successful capture result, target data or security boundary was changed. The source-derived affected case is the pcap summary's parsed count-contradiction branch. Real Wireshark incidence and MCP delivery were not tested. Comparing the selected tools' packet counts directly is a diagnostic workaround; it does not make contradictory results valid.

REA version

6.8.0; source revision 0d1a454e25db825567782e461da21530bad4b158. A later live-main check found the affected implementation unchanged; only unrelated desktop-application documentation had advanced.

Runtime and platform

Node.js v24.22.1; Linux aarch64, Debian bookworm container, uid 1000. Real util-linux prlimit; controlled shell producers with 4.6.6-stub banners; no native Wireshark execution.

Target and artifact context

Synthetic empty pcap header, no recorded traffic. TShark returns an empty JSON array in both runs; capinfos returns machine-readable pcap/Ethernet metadata and count zero or one. The one-packet claim is deliberately contradictory fixture output.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

  • Expected source: AGENTS.md, Architecture and Cleanup, requires preserving meaningful failure reasons; src/pcap/PcapProvider.ts:1025-1028 detects this comparison and constructs its specific count reason.
  • Failure source: The independently executed public CLI mismatch returns the exact JSON below with exit status 1 and empty stderr; its details property and count reason are absent. The control returns complete zero-packet Evidence with exit status 0.
  • Evidence provenance: observed; the public outputs were executed independently, while the internal error construction and propagation explanation are source-derived.
  • Local verification: reproduced through node scripts/rea.mjs inspect-pcap-capture ... --json with the inline fixtures and actual Linux command ownership/resource limiter.
  • Reproduction completeness: complete.

Mismatch stdout, verbatim:

{"code":"unreadable_output","category":"execution_failure","message":"Analysis returned an unreadable result. Run `rea doctor` and review the reported details; repeating the unchanged request is not expected to succeed.","retryable":false,"remediation":{"action":"Analysis returned an unreadable result. Run `rea doctor` and review the reported details; repeating the unchanged request is not expected to succeed."}}

The passing control's normalized_result includes packet_count: 0, coverage: "complete" and empty inventories. The client reports both tshark_identity_status: "verified" and capinfos_identity_status: "verified".

Typed outcome or recovery expected

A non-success result that identifies the capinfos-versus-TShark count disagreement. Its details and recovery advice should agree about which diagnostic information is available.

Analysis or suspected cause

Source-derived trace: src/cli/pcapCommands.ts:14-55 uses the production PcapAnalysisService and provider. PcapProvider.inspectCapture parses both tool outputs, verifies the snapshot, then throws the specific AnalysisProtocolError. The provider preserves that error and the service returns the failed result unchanged. src/cli/finishAnalysisCommand.ts projects it after close. src/domain/analysisErrorProjection.ts:273 maps its tag to unreadable_output; the detail classifiers have no branch preserving this bare protocol error's reason, and src/domain/analysisErrorPresentation.ts:426-428 supplies the generic message. This explanation does not prescribe an implementation or claim an executed MCP result.

Additional context

NOT_ENOUGH_INFO: last known good release and real-tool frequency. Current-source comparison found no drift in the relevant provider, parser, command, projection, CLI or instruction files. Open and closed duplicate searches and full likely-match discussions found related history but no current exact report. The open default-remediation work leaves diagnostic details unchanged; restoring that wording alone would not expose this count disagreement.

References

  • Closed issue #6433 concerned a directory selected as a tool before capture admission; its fix does not cover contradictory parsed producer counts.
  • Closed PR #6784 addressed that same tool-directory case and was closed unmerged because main already covered it.
  • Closed issue #6775 concerned malformed UTF-8 accepted as complete successful Evidence, rather than the missing reason on a correctly refused count contradiction.
  • Open PR #4829 separates generic recovery actions from messages and explicitly leaves diagnostics/details unchanged, so its restoration requirement is distinct.

Restoration check

Rerun the same fixture pair. The count-one case must remain refused and identify the packet-count disagreement, including the compared counts or an equally specific comparison reason. The count-zero case must still succeed with complete zero-packet Evidence. Merely changing the generic recovery wording without exposing the disagreement would leave this defect present. These are proposed fix-verification checks; no fix was made or tested.

Triage assessment

  • Impact level: P3
  • Assessment status: supported
  • Impact basis: The correct refusal loses its diagnostic reason and points to nonexistent details; the observed effect is diagnostic wording/information loss, with no incorrect successful analysis or data change.
  • Workaround status: available
  • Workaround basis: Compare the selected capinfos packet count with the selected TShark record count directly; the inline producers expose both values. This helps diagnose the refusal without treating contradictory results as successful Evidence.
Originally created by @coygeek on GitHub (Oct 26, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7293 ## Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ## Area Process capture or runtime observation ## Observed behavior `inspect-pcap-capture` correctly refuses contradictory producer results, but its CLI error loses the known reason. In the executed case, the selected capinfos reports one packet while the selected TShark returns `[]`. REA returns `unreadable_output` with no `details` property and tells the caller to review reported details. The provider constructs the specific reason `capinfos counted 1 packets but tshark returned 0`, but that reason is absent from the public result. The zero-packet control succeeds with `packet_count: 0` and `coverage: "complete"`. These are controlled producer fixtures exercising the actual public CLI, Linux process/resource boundary, parsing and result projection; they do not establish real Wireshark behavior. ## Reproduction Run the following from a built REA checkout on Linux with Node 24.22.1, Python 3 and util-linux `prlimit` available. The script creates a 24-byte empty pcap header and controlled executable shell fixtures. Their `--version` responses pass the documented Wireshark 4.x admission; their capture responses deliberately differ only in the capinfos packet count. It isolates home, config, cache and temporary files, then removes the fixtures. One mismatch run and one control were independently executed as uid 1000 in a Debian bookworm Linux arm64 container with networking disabled and the checkout mounted read-only. ```sh #!/bin/sh set -eu work="$(mktemp -d)" trap 'rm -rf "$work"' EXIT mkdir -p "$work/bin" "$work/home" "$work/config" "$work/cache" "$work/tmp" python3 - "$work" <<'FIXTURE' from pathlib import Path import struct, sys root = Path(sys.argv[1]) root.joinpath('capture.pcap').write_bytes(struct.pack('<IHHIIII', 0xa1b2c3d4, 2, 4, 0, 0, 65535, 1)) root.joinpath('bin/tshark').write_text("""#!/bin/sh if [ "$1" = "--version" ]; then printf 'TShark (Wireshark) 4.6.6-stub\n'; exit 0; fi printf '[]' """) for count in (0, 1): root.joinpath(f'bin/capinfos-{count}').write_text("""#!/bin/sh if [ "$1" = "--version" ]; then printf 'Capinfos (Wireshark) 4.6.6-stub\n'; exit 0; fi printf 'File type: pcap\nFile encapsulation: Ethernet\nNumber of packets: %s\n' """ % count) for tool in root.joinpath('bin').iterdir(): tool.chmod(0o755) FIXTURE for count in 0 1; do printf '\ncapinfos_count=%s\n' "$count" set +e HOME="$work/home" XDG_CONFIG_HOME="$work/config" XDG_CACHE_HOME="$work/cache" TMPDIR="$work/tmp" REA_TSHARK_COMMAND="$work/bin/tshark" REA_CAPINFOS_COMMAND="$work/bin/capinfos-$count" node scripts/rea.mjs inspect-pcap-capture "$work/capture.pcap" --json status=$? set -e printf 'exit_status=%s\n' "$status" done ``` ## Expected behavior Keep refusing the contradictory producer results, while reporting the concrete packet-count disagreement in a caller-visible reason or diagnostic. The repository's `AGENTS.md`, Architecture and Cleanup, requires preserving meaningful failure reasons. The refusal should provide the detail its recovery advice tells the caller to review. This report does not require partial success or a different error code. ## Impact and scope Observed once in one controlled mismatch attempt, with one passing zero-packet control. The capture is correctly refused; the diagnostic does not tell the caller why. No successful capture result, target data or security boundary was changed. The source-derived affected case is the pcap summary's parsed count-contradiction branch. Real Wireshark incidence and MCP delivery were not tested. Comparing the selected tools' packet counts directly is a diagnostic workaround; it does not make contradictory results valid. ## REA version 6.8.0; source revision `0d1a454e25db825567782e461da21530bad4b158`. A later live-main check found the affected implementation unchanged; only unrelated desktop-application documentation had advanced. ## Runtime and platform Node.js v24.22.1; Linux aarch64, Debian bookworm container, uid 1000. Real util-linux `prlimit`; controlled shell producers with 4.6.6-stub banners; no native Wireshark execution. ## Target and artifact context Synthetic empty pcap header, no recorded traffic. TShark returns an empty JSON array in both runs; capinfos returns machine-readable pcap/Ethernet metadata and count zero or one. The one-packet claim is deliberately contradictory fixture output. ## Interface CLI ## Earliest failure stage Transport or result projection ## Relevant output or evidence - Expected source: `AGENTS.md`, Architecture and Cleanup, requires preserving meaningful failure reasons; `src/pcap/PcapProvider.ts:1025-1028` detects this comparison and constructs its specific count reason. - Failure source: The independently executed public CLI mismatch returns the exact JSON below with exit status 1 and empty stderr; its `details` property and count reason are absent. The control returns complete zero-packet Evidence with exit status 0. - Evidence provenance: observed; the public outputs were executed independently, while the internal error construction and propagation explanation are source-derived. - Local verification: reproduced through `node scripts/rea.mjs inspect-pcap-capture ... --json` with the inline fixtures and actual Linux command ownership/resource limiter. - Reproduction completeness: complete. Mismatch stdout, verbatim: ```json {"code":"unreadable_output","category":"execution_failure","message":"Analysis returned an unreadable result. Run `rea doctor` and review the reported details; repeating the unchanged request is not expected to succeed.","retryable":false,"remediation":{"action":"Analysis returned an unreadable result. Run `rea doctor` and review the reported details; repeating the unchanged request is not expected to succeed."}} ``` The passing control's `normalized_result` includes `packet_count: 0`, `coverage: "complete"` and empty inventories. The client reports both `tshark_identity_status: "verified"` and `capinfos_identity_status: "verified"`. ## Typed outcome or recovery expected A non-success result that identifies the capinfos-versus-TShark count disagreement. Its details and recovery advice should agree about which diagnostic information is available. ## Analysis or suspected cause Source-derived trace: `src/cli/pcapCommands.ts:14-55` uses the production `PcapAnalysisService` and provider. `PcapProvider.inspectCapture` parses both tool outputs, verifies the snapshot, then throws the specific `AnalysisProtocolError`. The provider preserves that error and the service returns the failed result unchanged. `src/cli/finishAnalysisCommand.ts` projects it after close. `src/domain/analysisErrorProjection.ts:273` maps its tag to `unreadable_output`; the detail classifiers have no branch preserving this bare protocol error's reason, and `src/domain/analysisErrorPresentation.ts:426-428` supplies the generic message. This explanation does not prescribe an implementation or claim an executed MCP result. ## Additional context NOT_ENOUGH_INFO: last known good release and real-tool frequency. Current-source comparison found no drift in the relevant provider, parser, command, projection, CLI or instruction files. Open and closed duplicate searches and full likely-match discussions found related history but no current exact report. The open default-remediation work leaves diagnostic details unchanged; restoring that wording alone would not expose this count disagreement. ## References - [Closed issue #6433](https://github.com/morluto/rea/issues/6433) concerned a directory selected as a tool before capture admission; its fix does not cover contradictory parsed producer counts. - [Closed PR #6784](https://github.com/morluto/rea/pull/6784) addressed that same tool-directory case and was closed unmerged because main already covered it. - [Closed issue #6775](https://github.com/morluto/rea/issues/6775) concerned malformed UTF-8 accepted as complete successful Evidence, rather than the missing reason on a correctly refused count contradiction. - [Open PR #4829](https://github.com/morluto/rea/pull/4829) separates generic recovery actions from messages and explicitly leaves diagnostics/details unchanged, so its restoration requirement is distinct. ## Restoration check Rerun the same fixture pair. The count-one case must remain refused and identify the packet-count disagreement, including the compared counts or an equally specific comparison reason. The count-zero case must still succeed with complete zero-packet Evidence. Merely changing the generic recovery wording without exposing the disagreement would leave this defect present. These are proposed fix-verification checks; no fix was made or tested. ## Triage assessment - Impact level: P3 - Assessment status: supported - Impact basis: The correct refusal loses its diagnostic reason and points to nonexistent details; the observed effect is diagnostic wording/information loss, with no incorrect successful analysis or data change. - Workaround status: available - Workaround basis: Compare the selected capinfos packet count with the selected TShark record count directly; the inline producers expose both values. This helps diagnose the refusal without treating contradictory results as successful Evidence.
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#4332
No description provided.