[GH-ISSUE #6046] [Bug] All-failed APK package pulls discard typed device failures and their diagnostics #3693

Closed
opened 2026-10-31 00:43:07 +00:00 by bsakaguchi · 0 comments
Owner

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

Before submitting

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

Area

Evidence, artifacts, or reconstruction

Observed behavior

With valid client discovery and one APK returned by pm path, an ADB pull that reports error: device offline reaches pull-adb-package callers as generic unreadable_output, retryable: false, with no details or per-file failures. Calling pull-adb-file with the same executable and same device path preserves unsupported_target and the exact offline reason. The problem occurs after package path admission, at the all-failed aggregation boundary.

Reproduction

Executed through the built CLI with an inert ADB substitute. Its dispatch was:

#!/usr/bin/env node
const args = process.argv.slice(2);
if (args[0] === 'version') {
  console.log('Android Debug Bridge version 1.0.41\nVersion 34.0.5-stub');
  process.exit(0);
}
if (args.includes('path')) {
  console.log('package:/data/app/example/base.apk');
  process.exit(0);
}
if (args[2] === 'pull') {
  console.error('error: device offline');
  process.exit(1);
}
process.exit(1);

Save it as an executable adb in a fresh working directory and select that absolute path with REA_ADB_PATH. Run from a built REA checkout, using fresh output directories:

REA_ADB_PATH="$work_dir/adb" node scripts/rea.mjs pull-adb-package emulator-5554 com.example --output-directory "$work_dir/packages" --format json
REA_ADB_PATH="$work_dir/adb" node scripts/rea.mjs pull-adb-file emulator-5554 /data/app/example/base.apk --output-directory "$work_dir/files" --format json

Each command ran once, exited 1, and had empty CLI stderr. The first returned generic unreadable output; the second retained the offline refusal. No physical device, real ADB server, or naturally occurring disconnect was exercised.

Expected behavior

Keep the original typed primary failure when a single APK pull fails, and preserve per-file failure facts when composing multiple failures. runAdbCapture already classifies offline and timeout failures. The documented pull/deadline contract preserves per-file facts and provider_timeout; the single-file sibling passes its typed pull failure through.

Impact and scope

P2: callers lose the actual device failure and receive output-parser recovery advice. The source also maps all-failed timeouts to nonretryable unreadable output, losing timeout retryability; that deadline variant was not executed. The executed scope is one base APK with an offline response. Multiple failed splits and other typed causes follow the same source branch but were not separately exercised. Raw ADB invocation or the single-file acquisition workflow can expose the real failure before retrying on a reachable device. No successful APK artifact was lost in this reproduction.

REA version

rea-agents 6.7.0; source revision 5241597594.

Runtime and platform

Node.js v26.12.0; macOS 27.0.1 arm64; locked source dependencies and the supplied built CLI.

Target and artifact context

One simulated base APK path for package com.example on emulator-5554, reported through valid pm path output. No real Android device or APK bytes were transferred.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

Selected fields from the two actual JSON responses:

{"command":"pull-adb-package","code":"unreadable_output","category":"execution_failure","retryable":false}
{"command":"pull-adb-file","code":"unsupported_target","category":"unsupported_target","retryable":false,"details":{"operation":"pull_adb_file","path":"emulator-5554","reason":"error: device offline"}}

command labels identify separate responses. The package response has no details field and says: Analysis returned an unreadable result. Run rea doctor and review the reported details; repeating the unchanged request is not expected to succeed. The single-file response names the offline state.

Typed outcome or recovery expected

For this one-file case, preserve unsupported_target and error: device offline, with the selected device identity. For multiple failures, preserve typed causes and per-file paths rather than reporting an output-format failure solely because no artifact succeeded. A genuine timeout should retain provider_timeout and its retryability.

Analysis or suspected cause

The package loop collects each typed runAdb error, then the zero-artifact branch constructs a new AnalysisProtocolError. Original errors remain internally in an AggregateError, but the wrapper has no projected diagnostics or partial observation and becomes the public unreadable-output primary. This is source-derived explanation of the executed difference.

Additional context

Read #1903: it changes pm path name/collision/reservation diagnostics before pulls begin. #4720 explicitly excludes multi-APK pulls; #4655 concerns device/file operand attribution. #3369 is push checksum overflow, #4598 is late cancellation around digest failures, and #4594 is late command cancellation. #5190 and #4741 concern verification-script cleanup and Windows input-snapshot tests. #5971/#5978/#5981 do not cover this aggregation. Fetched upstream main 6d356b8434; the all-failed branch is unchanged. MCP transport and the 600-second timeout were not executed.

Originally created by @coygeek on GitHub (Oct 21, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6046 ### 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 Evidence, artifacts, or reconstruction ### Observed behavior With valid client discovery and one APK returned by `pm path`, an ADB pull that reports `error: device offline` reaches `pull-adb-package` callers as generic `unreadable_output`, `retryable: false`, with no `details` or per-file failures. Calling `pull-adb-file` with the same executable and same device path preserves `unsupported_target` and the exact offline reason. The problem occurs after package path admission, at the all-failed aggregation boundary. ### Reproduction Executed through the built CLI with an inert ADB substitute. Its dispatch was: ```js #!/usr/bin/env node const args = process.argv.slice(2); if (args[0] === 'version') { console.log('Android Debug Bridge version 1.0.41\nVersion 34.0.5-stub'); process.exit(0); } if (args.includes('path')) { console.log('package:/data/app/example/base.apk'); process.exit(0); } if (args[2] === 'pull') { console.error('error: device offline'); process.exit(1); } process.exit(1); ``` Save it as an executable `adb` in a fresh working directory and select that absolute path with `REA_ADB_PATH`. Run from a built REA checkout, using fresh output directories: ```sh REA_ADB_PATH="$work_dir/adb" node scripts/rea.mjs pull-adb-package emulator-5554 com.example --output-directory "$work_dir/packages" --format json REA_ADB_PATH="$work_dir/adb" node scripts/rea.mjs pull-adb-file emulator-5554 /data/app/example/base.apk --output-directory "$work_dir/files" --format json ``` Each command ran once, exited 1, and had empty CLI stderr. The first returned generic unreadable output; the second retained the offline refusal. No physical device, real ADB server, or naturally occurring disconnect was exercised. ### Expected behavior Keep the original typed primary failure when a single APK pull fails, and preserve per-file failure facts when composing multiple failures. [runAdbCapture already classifies offline and timeout failures](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/adb/AdbCommand.ts#L184-L216). [The documented pull/deadline contract](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/docs/adb-device-analysis.md#L163-L189) preserves per-file facts and `provider_timeout`; [the single-file sibling passes its typed pull failure through](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/adb/AdbProvider.ts#L2313-L2325). ### Impact and scope P2: callers lose the actual device failure and receive output-parser recovery advice. The source also maps all-failed timeouts to nonretryable unreadable output, losing timeout retryability; that deadline variant was not executed. The executed scope is one base APK with an offline response. Multiple failed splits and other typed causes follow the same source branch but were not separately exercised. Raw ADB invocation or the single-file acquisition workflow can expose the real failure before retrying on a reachable device. No successful APK artifact was lost in this reproduction. ### REA version rea-agents 6.7.0; source revision 52415975942a4b9c53a817915b313ccc404f280e. ### Runtime and platform Node.js v26.12.0; macOS 27.0.1 arm64; locked source dependencies and the supplied built CLI. ### Target and artifact context One simulated base APK path for package com.example on emulator-5554, reported through valid pm path output. No real Android device or APK bytes were transferred. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence Selected fields from the two actual JSON responses: ```json {"command":"pull-adb-package","code":"unreadable_output","category":"execution_failure","retryable":false} {"command":"pull-adb-file","code":"unsupported_target","category":"unsupported_target","retryable":false,"details":{"operation":"pull_adb_file","path":"emulator-5554","reason":"error: device offline"}} ``` `command` labels identify separate responses. The package response has no `details` field and says: `Analysis returned an unreadable result. Run rea doctor and review the reported details; repeating the unchanged request is not expected to succeed.` The single-file response names the offline state. ### Typed outcome or recovery expected For this one-file case, preserve `unsupported_target` and `error: device offline`, with the selected device identity. For multiple failures, preserve typed causes and per-file paths rather than reporting an output-format failure solely because no artifact succeeded. A genuine timeout should retain `provider_timeout` and its retryability. ### Analysis or suspected cause [The package loop collects each typed runAdb error](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/adb/AdbProvider.ts#L2134-L2162), then [the zero-artifact branch constructs a new AnalysisProtocolError](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/adb/AdbProvider.ts#L2248-L2259). Original errors remain internally in an AggregateError, but the wrapper has no projected diagnostics or partial observation and becomes the public unreadable-output primary. This is source-derived explanation of the executed difference. ### Additional context Read #1903: it changes pm path name/collision/reservation diagnostics before pulls begin. #4720 explicitly excludes multi-APK pulls; #4655 concerns device/file operand attribution. #3369 is push checksum overflow, #4598 is late cancellation around digest failures, and #4594 is late command cancellation. #5190 and #4741 concern verification-script cleanup and Windows input-snapshot tests. #5971/#5978/#5981 do not cover this aggregation. Fetched upstream main 6d356b84344659085f2b912857b5e27fe0160c9b; the all-failed branch is unchanged. MCP transport and the 600-second timeout were not executed.
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#3693
No description provided.