[GH-ISSUE #4594] [Bug] ADB command consumers replace completed failures with late cancellation #2385

Closed
opened 2026-10-17 21:03:59 +00:00 by bsakaguchi · 2 comments
Owner

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

Before submitting

  • Searched open and closed issues for ADB late cancellation and abort reports. #3886 separately covers version timeout classification; #4251 covers screen publication.
  • Removed credentials and sensitive target data.

Area

Provider or capability discovery / process lifecycle

Observed behavior

Controlled real-process tests on source 9a95db681 show ADB command and version-probe consumers replace already completed failures with cancellation when an abort arrives at their promise handoff. A real active-process cancellation wraps the caller's reason instead of retaining it as the typed error's exact cause. A foreign ABORT_ERR string also passes as cancellation without the command owner's cancellation marker.

Reproduction

Executed npm run test:focused -- tests/boundary/providers/adb/adbCommandFinalization.test.ts src/adb/AdbCommand.test.ts.
The boundary fixture runs actual Node child processes through execFileBytes/execFileOutput; a test wrapper aborts only after the producer settles, before its ADB consumer resumes. Controlled cases cover exit 7, unauthorized stderr, timeout, output overflow, and a missing version binary. An active child writes a readiness file before cancellation; the test awaits its owned terminal promise.
Result across both files: 14 failed, 17 passed. This includes three separate #3886 timeout controls. Unit controls also cover null/string/Error reasons, a foreign ABORT_ERR, and a physical error that is itself used as the later abort reason. All completed-byte/application Evidence controls pass.

Expected behavior

Only producer-recorded cancellation establishes cancellation. Preserve the exact caller reason and available captured output; an existing physical failure remains primary despite later abort. Successful command bytes remain available for the consuming provider to validate and assemble Evidence before application completion checks cancellation.

Impact and scope

Observed in controlled real-process handoff/active-cancellation tests and source tests, without an actual adb binary or Android device. Native Windows/Linux behavior and spontaneous failure frequency: NOT_ENOUGH_INFO; untested.

REA version

9a95db6819

Runtime and platform

Node 24.18.0, macOS arm64. Client-script controls use a Unix executable fixture and are skipped on Windows.

Target and artifact context

Synthetic Node child processes and temporary client executables; no device or server contacted.

Interface

Other: production command/provider boundary; public CLI timeout covered under #3886.

Earliest failure stage

Cleanup, cancellation, or lifecycle

Relevant output or evidence

runAdbCapture and inspectAdbClient classify with signal?.aborted || failure?.code === "ABORT_ERR". The command producer already records cancellation in ExecFileOutputCancelledError with the exact reason as its cause. The ADB consumer ignores that authority and wraps the rejection instead.

Typed outcome or recovery expected

Physical protocol/unsupported/timeout/resource failure retains its original classification and cause. Actual producer cancellation returns AnalysisCancelledError with cause identical to the producer's caller reason and retained captured output.

Analysis or suspected cause

Source-derived: ADB interprets the later consumer signal independently of the command owner. Use the owner's tagged cancellation and normalize its parsed output once for the ADB error projection. A neighboring digest path has a similar source-only symptom but requires shared file-owner cancellation metadata; this report's reproduction covers subprocess paths.

Additional context

Related: #3886, #4227. No actual adb/device runtime behavior claimed.

Originally created by @morluto on GitHub (Oct 16, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4594 ## Before submitting - [x] Searched open and closed issues for ADB late cancellation and abort reports. #3886 separately covers version timeout classification; #4251 covers screen publication. - [x] Removed credentials and sensitive target data. ## Area Provider or capability discovery / process lifecycle ## Observed behavior Controlled real-process tests on source 9a95db681 show ADB command and version-probe consumers replace already completed failures with cancellation when an abort arrives at their promise handoff. A real active-process cancellation wraps the caller's reason instead of retaining it as the typed error's exact cause. A foreign `ABORT_ERR` string also passes as cancellation without the command owner's cancellation marker. ## Reproduction Executed `npm run test:focused -- tests/boundary/providers/adb/adbCommandFinalization.test.ts src/adb/AdbCommand.test.ts`. The boundary fixture runs actual Node child processes through execFileBytes/execFileOutput; a test wrapper aborts only after the producer settles, before its ADB consumer resumes. Controlled cases cover exit 7, unauthorized stderr, timeout, output overflow, and a missing version binary. An active child writes a readiness file before cancellation; the test awaits its owned terminal promise. Result across both files: 14 failed, 17 passed. This includes three separate #3886 timeout controls. Unit controls also cover null/string/Error reasons, a foreign ABORT_ERR, and a physical error that is itself used as the later abort reason. All completed-byte/application Evidence controls pass. ## Expected behavior Only producer-recorded cancellation establishes cancellation. Preserve the exact caller reason and available captured output; an existing physical failure remains primary despite later abort. Successful command bytes remain available for the consuming provider to validate and assemble Evidence before application completion checks cancellation. ## Impact and scope Observed in controlled real-process handoff/active-cancellation tests and source tests, without an actual adb binary or Android device. Native Windows/Linux behavior and spontaneous failure frequency: NOT_ENOUGH_INFO; untested. ## REA version 9a95db681903c5934cbfab868626483fd6dc2464 ## Runtime and platform Node 24.18.0, macOS arm64. Client-script controls use a Unix executable fixture and are skipped on Windows. ## Target and artifact context Synthetic Node child processes and temporary client executables; no device or server contacted. ## Interface Other: production command/provider boundary; public CLI timeout covered under #3886. ## Earliest failure stage Cleanup, cancellation, or lifecycle ## Relevant output or evidence [runAdbCapture](https://github.com/morluto/rea/blob/9a95db681903c5934cbfab868626483fd6dc2464/src/adb/AdbCommand.ts#L72) and [inspectAdbClient](https://github.com/morluto/rea/blob/9a95db681903c5934cbfab868626483fd6dc2464/src/adb/AdbConfiguration.ts#L115) classify with `signal?.aborted || failure?.code === "ABORT_ERR"`. The command producer already records cancellation in ExecFileOutputCancelledError with the exact reason as its cause. The ADB consumer ignores that authority and wraps the rejection instead. ## Typed outcome or recovery expected Physical protocol/unsupported/timeout/resource failure retains its original classification and cause. Actual producer cancellation returns AnalysisCancelledError with cause identical to the producer's caller reason and retained captured output. ## Analysis or suspected cause Source-derived: ADB interprets the later consumer signal independently of the command owner. Use the owner's tagged cancellation and normalize its parsed output once for the ADB error projection. A neighboring digest path has a similar source-only symptom but requires shared file-owner cancellation metadata; this report's reproduction covers subprocess paths. ## Additional context Related: #3886, #4227. No actual adb/device runtime behavior claimed.
Author
Owner

@kaoru0822-kitauji commented on GitHub (Oct 17, 2026):

This appears fixed on current main (2092f90b7) by c4475d4a6 and 0d2247428 (the commit message references this issue).

Executed on main 2092f90b7 (macOS arm64, Node 24): npm run test:focused -- … including src/adb/AdbCommand.test.ts (17 tests), tests/boundary/providers/adb/adbCommandFinalization.test.ts (18 tests) — all passed (205/205 across the 13 files checked in this batch).

I did not rerun the original fault injection from the report separately; the tests above are the regressions added with the fix. Leaving closure to a maintainer.

<!-- gh-comment-id:6232496769 --> @kaoru0822-kitauji commented on GitHub (Oct 17, 2026): This appears fixed on current main (2092f90b7) by c4475d4a6 and 0d2247428 (the commit message references this issue). Executed on main 2092f90b7 (macOS arm64, Node 24): `npm run test:focused -- …` including `src/adb/AdbCommand.test.ts` (17 tests), `tests/boundary/providers/adb/adbCommandFinalization.test.ts` (18 tests) — all passed (205/205 across the 13 files checked in this batch). I did not rerun the original fault injection from the report separately; the tests above are the regressions added with the fix. Leaving closure to a maintainer.
Author
Owner

@morluto commented on GitHub (Oct 18, 2026):

Closing as fixed on main after reconciling this report with the landed owner/consumer changes.

  • 0d2247428: fix(adb): preserve version probe failures during admission. Remaining related work: shared file-close cancellation provenance for digest consumers requires a separate producer and consumer migration.
  • c4475d4a6: fix(adb): preserve command owner cancellation outcomes.

Evidence scope: this closure uses the landed source, regression coverage and validation already recorded in the linked commits/thread. No new local tests or native-provider reproduction were run during this backlog pass; previously documented platform and real-provider gaps still apply.

<!-- gh-comment-id:6255999877 --> @morluto commented on GitHub (Oct 18, 2026): <!-- rea-backlog-reconciliation-2026-10-19-4594 --> Closing as fixed on `main` after reconciling this report with the landed owner/consumer changes. - [0d2247428](https://github.com/morluto/rea/commit/0d224742808e32106e2ee93340c6755ee5e0a0db): fix(adb): preserve version probe failures during admission. Remaining related work: shared file-close cancellation provenance for digest consumers requires a separate producer and consumer migration. - [c4475d4a6](https://github.com/morluto/rea/commit/c4475d4a673966121605e417a69bc9ab94bda861): fix(adb): preserve command owner cancellation outcomes. Evidence scope: this closure uses the landed source, regression coverage and validation already recorded in the linked commits/thread. No new local tests or native-provider reproduction were run during this backlog pass; previously documented platform and real-provider gaps still apply.
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#2385
No description provided.