[GH-ISSUE #5877] [Bug] Incomplete firmware range errors include an internal input path prefix #3564

Closed
opened 2026-10-31 00:41:54 +00:00 by bsakaguchi · 2 comments
Owner

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

Before submitting

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

Area

CLI

Observed behavior

extract-firmware with only --offset or only --length correctly rejects the incomplete range, but its JSON correction path includes an internal input member. Offset-only input returns ["input", "range", "length"]; length-only input returns ["input", "range", "offset"]. The declared firmware arguments contain range directly and have no input property.

Both cases were executed once through the built CLI. This report concerns the extra path segment, not the error classification or refusal.

Reproduction

From a built source checkout, run these commands. No firmware engine is needed for the incomplete-range cases.

work_dir="$(mktemp -d)"
mkdir -p "$work_dir/home" "$work_dir/config" "$work_dir/data" \
  "$work_dir/cache" "$work_dir/state" "$work_dir/temp"
: > "$work_dir/firmware.bin"
run_rea() {
  env -i PATH="$PATH" HOME="$work_dir/home" \
    XDG_CONFIG_HOME="$work_dir/config" XDG_DATA_HOME="$work_dir/data" \
    XDG_CACHE_HOME="$work_dir/cache" XDG_STATE_HOME="$work_dir/state" \
    TMPDIR="$work_dir/temp" REA_LOG_LEVEL=silent \
    node scripts/rea.mjs "$@"
}
run_rea extract-firmware "$work_dir/firmware.bin" "$work_dir/out-offset" --offset 5 --json
run_rea extract-firmware "$work_dir/firmware.bin" "$work_dir/out-length" --length 5 --json
run_rea extract-firmware "$work_dir/firmware.bin" "$work_dir/out-paired" --offset 5 --length 5 --json

Both incomplete calls exited 1 with empty stderr and the issue paths below. The paired control passed validation and reached provider admission: on this host it returned capability_unavailable for Unblob, requiring Linux and a configured absolute tool path. Successful extraction was not tested.

Expected behavior

Keep identifying the missing companion field, with its path relative to the declared operation arguments: ["range", "length"] or ["range", "offset"]. Preserve the correct refusal and reason.

The firmware guide's request examples put range directly in the arguments. AnalysisInputIssue describes correction metadata for a rejected caller argument. The shared provider-operation implementation explicitly strips the same internal input prefix.

Impact and scope

P3 diagnostic defect: the paths name a nonexistent intermediate property, but both calls are refused correctly and retain the missing field name and reason. CLI help documents that offset and length must be supplied together; supplying both passed validation in the control. No downstream automated-repair failure or incorrect analysis result was observed.

Scope is the incomplete-range CLI cases above. Production stdio MCP calls with missing path, missing range length, or negative range offset were also tested; they were rejected by MCP schema validation before this service and did not exhibit this prefix. A missing CLI path or negative CLI offset likewise fails earlier parsing. This report does not claim every firmware rejection is affected.

REA version

rea-agents 6.7.0; source revision 52415975942a4b9c53a817915b313ccc404f280e.

Runtime and platform

Node.js v26.12.0; macOS 27.0.1, arm64. Built public CLI and production stdio MCP server; no firmware provider executed.

Target and artifact context

Generated empty local file and absent output destinations. Range validation precedes provider admission and file analysis; no real firmware sample or device was used.

Interface

CLI

Earliest failure stage

Request parsing or validation

Relevant output or evidence

Selected JSON fields from the executed offset-only call:

{
  "code": "invalid_request",
  "category": "invalid_input",
  "retryable": false,
  "recovery": {
    "kind": "inspect_input_contract",
    "operation": "extract_firmware"
  },
  "details": {
    "operation": "extract_firmware",
    "issues": [{
      "path": ["input", "range", "length"],
      "reason": "missing_argument",
      "expected": "number"
    }]
  }
}

The length-only result has the same fields with path ["input", "range", "offset"]. Remediation directs the caller to the declared input schema or CLI usage and says to correct the listed fields.

The existing firmware validation test and CLI boundary test currently assert this prefix. They corroborate the implementation behavior; the test expectations would need to follow the caller-relative contract if it is corrected.

Typed outcome or recovery expected

Keep invalid_request, invalid_input, missing_argument, and input-contract recovery. Normalize only the synthetic wrapper segment so the correction path identifies the operation argument.

Analysis or suspected cause

Source-derived: FirmwareAnalysisService.execute validates { operation, input } and projects its Zod issue paths unchanged. The CLI adapter passes the inner object and creates a partial range for either single companion option. The internal wrapper consequently leaks into the returned path.

Additional context

Recent-history inspection identifies introducing commit 1629266e3c08c90fed6bba5383528af7986a12b7, fix(errors): preserve canonical failures and correction details. It added the wrapper-level projection and both test assertions. Its parent supplied no structured issues at this boundary; no version with correct firmware issue paths was established or executed. This is an introduced diagnostic defect in the correction-detail change.

Related issue #5402 reports the earlier absence of missing-companion details and explicitly does not require an exact path prefix. This report concerns the synthetic segment in the newly added details. Issues #5745, #5746 and #5846 address extraction gaps, destination preconditions and staging-budget classification, respectively.

Fetched main f5410bdc4c86de564ddb24f24df86c41cfdd8bec has no changes to the relevant service, schema, CLI or error-projection paths since the tested baseline. This is a source comparison, not a runtime replay of that later revision.

Originally created by @coygeek on GitHub (Oct 21, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5877 ### 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 CLI ### Observed behavior `extract-firmware` with only `--offset` or only `--length` correctly rejects the incomplete range, but its JSON correction path includes an internal `input` member. Offset-only input returns `["input", "range", "length"]`; length-only input returns `["input", "range", "offset"]`. The declared firmware arguments contain `range` directly and have no `input` property. Both cases were executed once through the built CLI. This report concerns the extra path segment, not the error classification or refusal. ### Reproduction From a built source checkout, run these commands. No firmware engine is needed for the incomplete-range cases. ```sh work_dir="$(mktemp -d)" mkdir -p "$work_dir/home" "$work_dir/config" "$work_dir/data" \ "$work_dir/cache" "$work_dir/state" "$work_dir/temp" : > "$work_dir/firmware.bin" run_rea() { env -i PATH="$PATH" HOME="$work_dir/home" \ XDG_CONFIG_HOME="$work_dir/config" XDG_DATA_HOME="$work_dir/data" \ XDG_CACHE_HOME="$work_dir/cache" XDG_STATE_HOME="$work_dir/state" \ TMPDIR="$work_dir/temp" REA_LOG_LEVEL=silent \ node scripts/rea.mjs "$@" } run_rea extract-firmware "$work_dir/firmware.bin" "$work_dir/out-offset" --offset 5 --json run_rea extract-firmware "$work_dir/firmware.bin" "$work_dir/out-length" --length 5 --json run_rea extract-firmware "$work_dir/firmware.bin" "$work_dir/out-paired" --offset 5 --length 5 --json ``` Both incomplete calls exited 1 with empty stderr and the issue paths below. The paired control passed validation and reached provider admission: on this host it returned `capability_unavailable` for Unblob, requiring Linux and a configured absolute tool path. Successful extraction was not tested. ### Expected behavior Keep identifying the missing companion field, with its path relative to the declared operation arguments: `["range", "length"]` or `["range", "offset"]`. Preserve the correct refusal and reason. The [firmware guide's request examples](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/docs/firmware-analysis.md#L53-L80) put `range` directly in the arguments. [AnalysisInputIssue](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/analysisErrorCore.ts#L79-L90) describes correction metadata for a rejected caller argument. The [shared provider-operation implementation](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/application/ProviderOperationExecution.ts#L61-L73) explicitly strips the same internal `input` prefix. ### Impact and scope P3 diagnostic defect: the paths name a nonexistent intermediate property, but both calls are refused correctly and retain the missing field name and reason. CLI help documents that offset and length must be supplied together; supplying both passed validation in the control. No downstream automated-repair failure or incorrect analysis result was observed. Scope is the incomplete-range CLI cases above. Production stdio MCP calls with missing path, missing range length, or negative range offset were also tested; they were rejected by MCP schema validation before this service and did not exhibit this prefix. A missing CLI path or negative CLI offset likewise fails earlier parsing. This report does not claim every firmware rejection is affected. ### REA version rea-agents 6.7.0; source revision `52415975942a4b9c53a817915b313ccc404f280e`. ### Runtime and platform Node.js v26.12.0; macOS 27.0.1, arm64. Built public CLI and production stdio MCP server; no firmware provider executed. ### Target and artifact context Generated empty local file and absent output destinations. Range validation precedes provider admission and file analysis; no real firmware sample or device was used. ### Interface CLI ### Earliest failure stage Request parsing or validation ### Relevant output or evidence Selected JSON fields from the executed offset-only call: ```json { "code": "invalid_request", "category": "invalid_input", "retryable": false, "recovery": { "kind": "inspect_input_contract", "operation": "extract_firmware" }, "details": { "operation": "extract_firmware", "issues": [{ "path": ["input", "range", "length"], "reason": "missing_argument", "expected": "number" }] } } ``` The length-only result has the same fields with path `["input", "range", "offset"]`. Remediation directs the caller to the declared input schema or CLI usage and says to correct the listed fields. The [existing firmware validation test](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/tests/boundary/firmware/firmwareValidationProjection.test.ts#L40-L54) and [CLI boundary test](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/tests/boundary/cli/firmwareIncompleteRange.test.ts#L37-L53) currently assert this prefix. They corroborate the implementation behavior; the test expectations would need to follow the caller-relative contract if it is corrected. ### Typed outcome or recovery expected Keep `invalid_request`, `invalid_input`, `missing_argument`, and input-contract recovery. Normalize only the synthetic wrapper segment so the correction path identifies the operation argument. ### Analysis or suspected cause Source-derived: [FirmwareAnalysisService.execute](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/application/firmware/FirmwareAnalysisService.ts#L37-L46) validates `{ operation, input }` and projects its Zod issue paths unchanged. The [CLI adapter](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/cli/firmwareCommands.ts#L78-L88) passes the inner object and creates a partial range for either single companion option. The internal wrapper consequently leaks into the returned path. ### Additional context Recent-history inspection identifies introducing commit [1629266e3c08c90fed6bba5383528af7986a12b7](https://github.com/morluto/rea/commit/1629266e3c08c90fed6bba5383528af7986a12b7), `fix(errors): preserve canonical failures and correction details`. It added the wrapper-level projection and both test assertions. Its parent supplied no structured issues at this boundary; no version with correct firmware issue paths was established or executed. This is an introduced diagnostic defect in the correction-detail change. Related issue #5402 reports the earlier absence of missing-companion details and explicitly does not require an exact path prefix. This report concerns the synthetic segment in the newly added details. Issues #5745, #5746 and #5846 address extraction gaps, destination preconditions and staging-budget classification, respectively. Fetched main `f5410bdc4c86de564ddb24f24df86c41cfdd8bec` has no changes to the relevant service, schema, CLI or error-projection paths since the tested baseline. This is a source comparison, not a runtime replay of that later revision.
Author
Owner

@CassieFox23 commented on GitHub (Oct 23, 2026):

I'd like to take this one. With only --offset or only --length, the refusal is right, but the JSON path starts with an internal input member. The fix drops that prefix, so the path reads ["range", "length"] or ["range", "offset"]. The shared provider code already strips the same prefix. Two tests pin the old path today, so the PR will update them and say why.

Thanks, coygeek, for the clear report with both cases.

🤖 Written with Claude Code (Opus 5.5), posted with my OK 🦊

<!-- gh-comment-id:6370424603 --> @CassieFox23 commented on GitHub (Oct 23, 2026): I'd like to take this one. With only `--offset` or only `--length`, the refusal is right, but the JSON path starts with an internal `input` member. The fix drops that prefix, so the path reads `["range", "length"]` or `["range", "offset"]`. The shared provider code already strips the same prefix. Two tests pin the old path today, so the PR will update them and say why. Thanks, coygeek, for the clear report with both cases. 🤖 Written with Claude Code (Opus 5.5), posted with my OK 🦊
Author
Owner

@coygeek commented on GitHub (Oct 24, 2026):

Checked the reported fix on main at d87e73f2db.

FirmwareAnalysisService strips only the leading internal input envelope from projected validation paths. Both shared-service and compiled-CLI tests now assert range/missing-field directly for offset-only and length-only cases; refusal classification is retained.

Implementation: FirmwareAnalysisService.ts, firmwareIncompleteRange.test.ts.

The relevant regression checks in firmwareIncompleteRange.test.ts, firmwareValidationProjection.test.ts passed in the focused test run on this revision. This closure is based on the current source and those checks; provider fixtures do not establish a real-engine run. Closing as completed on main.

<!-- gh-comment-id:6380756647 --> @coygeek commented on GitHub (Oct 24, 2026): Checked the reported fix on `main` at d87e73f2db50be72d33a4b3c7199af35518b441c. FirmwareAnalysisService strips only the leading internal input envelope from projected validation paths. Both shared-service and compiled-CLI tests now assert range/missing-field directly for offset-only and length-only cases; refusal classification is retained. Implementation: [FirmwareAnalysisService.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/src/application/firmware/FirmwareAnalysisService.ts#L42), [firmwareIncompleteRange.test.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/tests/boundary/cli/firmwareIncompleteRange.test.ts#L48). The relevant regression checks in [firmwareIncompleteRange.test.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/tests/boundary/cli/firmwareIncompleteRange.test.ts), [firmwareValidationProjection.test.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/tests/boundary/firmware/firmwareValidationProjection.test.ts) passed in the focused test run on this revision. This closure is based on the current source and those checks; provider fixtures do not establish a real-engine run. Closing as completed on main.
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#3564
No description provided.