[GH-ISSUE #5689] [Bug] inspect-adb-client hides execution failures behind a version diagnostic #3441

Closed
opened 2026-10-31 00:40:30 +00:00 by bsakaguchi · 3 comments
Owner

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

Before submitting

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

Area

Provider or capability discovery

Observed behavior

When an absolute REA_ADB_PATH selects a directory or a regular file without execute permission, node scripts/rea.mjs inspect-adb-client --json exits 1 with a generic version diagnostic. The public message, remediation, and reason omit the selected path, setting name, and actual execution failure. The client could not start; this is not a process returning an unrecognized version.

Reproduction

From the built source checkout with its locked dependencies installed, run on a POSIX host. No Android device or installed adb is required:

work_dir="$(mktemp -d)"
mkdir -p "$work_dir/home" "$work_dir/cfg" "$work_dir/data" \
  "$work_dir/cache" "$work_dir/state" "$work_dir/tmp" "$work_dir/adb-dir"
cat > "$work_dir/adb-file" <<'SH'
#!/bin/sh
printf 'Android Debug Bridge version 1.0.41\nVersion 34.0.5-11673356\n'
SH
chmod 644 "$work_dir/adb-file"
run_rea() {
  env -i PATH="$PATH" HOME="$work_dir/home" \
    XDG_CONFIG_HOME="$work_dir/cfg" XDG_DATA_HOME="$work_dir/data" \
    XDG_CACHE_HOME="$work_dir/cache" XDG_STATE_HOME="$work_dir/state" \
    TMPDIR="$work_dir/tmp" REA_LOG_LEVEL=silent REA_ADB_PATH="$1" \
    node scripts/rea.mjs inspect-adb-client --json
}
run_rea "$work_dir/adb-dir"
printf 'directory exit: %s\n' "$?"
run_rea "$work_dir/adb-file"
printf 'non-executable file exit: %s\n' "$?"
run_rea "$work_dir/missing-adb"
printf 'missing path exit: %s\n' "$?"
chmod 755 "$work_dir/adb-file"
run_rea "$work_dir/adb-file"
printf 'executable file exit: %s\n' "$?"

The independent verifier ran this reproduction, and the submitter repeated it once at the baseline below. Both unusable inputs exit 1 with the identical diagnostic shown below. The missing-path control exits 1 but names the selected path and REA_ADB_PATH. Changing only the file's execute permission makes inspection succeed with version 34.0.5-11673356, path_source: environment, and contacted_adb_server: false.

Expected behavior

Keep readiness refused, but preserve the caller-selected path and meaningful execution failure, with recovery guidance for the affected REA_ADB_PATH configuration. Distinguish an unusable existing path from a missing binary and from actual unrecognized version output. Preserve the existing missing-path advice and executable control.

The repository contract requires preserving caller-selected paths; line 31 requires meaningful failure reasons. The ADB guide describes the selected client and readiness probe. Its explicit setting-specific recovery promise concerns missing binaries; the general preservation contract grounds this existing-but-unusable case.

Impact and scope

P3: misleading diagnostic wording for an already unusable client. Readiness still refuses correctly; no false success, device action, or data change was observed. A practical workaround is to select an executable adb client or correct its execute permission when execution is intended; the same fixture succeeds after chmod 755. Observed scope is explicit absolute selection on macOS. Windows, PATH discovery, a real adb installation, connected-device operations, and MCP transport were not tested.

REA version

rea-agents 6.7.0, source baseline 9d8e7803326a382cbbb3ffdb900f5e93e5442d68. Fetched and checked origin/main at 7dd6941393c852a3324cf01c2bd79a9dcff43728: no intervening commits change the cited contract, documentation, ADB configuration/provider/CLI/contract files, or shared configuration-refusal helper. Runtime reproduction was repeated at the baseline; current main was checked through source history, not separately built or executed.

Runtime and platform

Node.js v26.12.0; macOS 27.0.1; arm64.

Target and artifact context

A local empty directory and an inert shell script with mode 0644, both selected through absolute REA_ADB_PATH values. Isolated HOME, XDG directories, and temporary directory. No analysis target or Android device.

Interface

CLI

Earliest failure stage

Setup or provider admission

Relevant output or evidence

Both unusable-path invocations return this stdout with exit 1 and empty stderr:

{"code":"capability_unavailable","category":"unsupported_provider","message":"The selected adb binary did not report a usable version.","retryable":false,"remediation":{"action":"The selected adb binary did not report a usable version."},"details":{"provider_id":"adb","operation":"inspect_adb_client","reason":"The selected adb binary did not report a usable version."}}

The independent verifier's direct process probes returned EACCES for both fixtures and confirmed that the internal configuration failure retained the selected path and error code. The public refusal above loses both. Evidence provenance: observed; local verification: independently reproduced and repeated by the submitter. These fixture controls do not verify a real adb installation.

Typed outcome or recovery expected

An actionable unavailable-client refusal preserving the selected path and execution reason. Do not imply that the path was missing or that a running adb returned unusable version output. Keep missing-path and executable-client controls working. Repeating these same controls after a fix is the proposed restoration check; no fix has been tested.

Analysis or suspected cause

Source-derived reasoning: AdbConfiguration.ts:164-188 handles ENOENT separately, but maps EACCES to version_unresolved with generic version wording while retaining selected_binary and exit_code. providerConfigurationRefusal.ts:12-20 projects only the message and optional remediation; these failures provide no remediation. This agrees with the observed CLI result. No bundled dependency was identified as the root cause.

Additional context

Still reproduces after #1952, whose missing/relative-path fix is present in the baseline via merged #1954 (39418ea173763ca55d4f116992ee903bcaeb1898). A comment on the closed issue also noted the remaining directory/non-executable triggers. This report isolates that unresolved behavior; it does not claim a known-good version or a later reintroduction.

Related #5177 and open PR #5180 address Apktool's non-executable launcher being called missing; #5401 addresses objdump artifact acquisition. Their adapter paths and restoration signals differ. Closed #3886 covers ADB timeout identity; #3347 and #3337 cover Apktool deadlines and lifecycle behavior. None establishes restoration of this ADB execution-refusal diagnostic. Prepared with AI assistance.

Originally created by @coygeek on GitHub (Oct 20, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5689 ### 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 Provider or capability discovery ### Observed behavior When an absolute `REA_ADB_PATH` selects a directory or a regular file without execute permission, `node scripts/rea.mjs inspect-adb-client --json` exits 1 with a generic version diagnostic. The public message, remediation, and reason omit the selected path, setting name, and actual execution failure. The client could not start; this is not a process returning an unrecognized version. ### Reproduction From the built source checkout with its locked dependencies installed, run on a POSIX host. No Android device or installed adb is required: ```sh work_dir="$(mktemp -d)" mkdir -p "$work_dir/home" "$work_dir/cfg" "$work_dir/data" \ "$work_dir/cache" "$work_dir/state" "$work_dir/tmp" "$work_dir/adb-dir" cat > "$work_dir/adb-file" <<'SH' #!/bin/sh printf 'Android Debug Bridge version 1.0.41\nVersion 34.0.5-11673356\n' SH chmod 644 "$work_dir/adb-file" run_rea() { env -i PATH="$PATH" HOME="$work_dir/home" \ XDG_CONFIG_HOME="$work_dir/cfg" XDG_DATA_HOME="$work_dir/data" \ XDG_CACHE_HOME="$work_dir/cache" XDG_STATE_HOME="$work_dir/state" \ TMPDIR="$work_dir/tmp" REA_LOG_LEVEL=silent REA_ADB_PATH="$1" \ node scripts/rea.mjs inspect-adb-client --json } run_rea "$work_dir/adb-dir" printf 'directory exit: %s\n' "$?" run_rea "$work_dir/adb-file" printf 'non-executable file exit: %s\n' "$?" run_rea "$work_dir/missing-adb" printf 'missing path exit: %s\n' "$?" chmod 755 "$work_dir/adb-file" run_rea "$work_dir/adb-file" printf 'executable file exit: %s\n' "$?" ``` The independent verifier ran this reproduction, and the submitter repeated it once at the baseline below. Both unusable inputs exit 1 with the identical diagnostic shown below. The missing-path control exits 1 but names the selected path and `REA_ADB_PATH`. Changing only the file's execute permission makes inspection succeed with version `34.0.5-11673356`, `path_source: environment`, and `contacted_adb_server: false`. ### Expected behavior Keep readiness refused, but preserve the caller-selected path and meaningful execution failure, with recovery guidance for the affected `REA_ADB_PATH` configuration. Distinguish an unusable existing path from a missing binary and from actual unrecognized version output. Preserve the existing missing-path advice and executable control. The [repository contract](https://github.com/morluto/rea/blob/9d8e7803326a382cbbb3ffdb900f5e93e5442d68/AGENTS.md#L13) requires preserving caller-selected paths; [line 31](https://github.com/morluto/rea/blob/9d8e7803326a382cbbb3ffdb900f5e93e5442d68/AGENTS.md#L31) requires meaningful failure reasons. The [ADB guide](https://github.com/morluto/rea/blob/9d8e7803326a382cbbb3ffdb900f5e93e5442d68/docs/adb-device-analysis.md#L14-L29) describes the selected client and readiness probe. Its explicit setting-specific recovery promise concerns missing binaries; the general preservation contract grounds this existing-but-unusable case. ### Impact and scope P3: misleading diagnostic wording for an already unusable client. Readiness still refuses correctly; no false success, device action, or data change was observed. A practical workaround is to select an executable adb client or correct its execute permission when execution is intended; the same fixture succeeds after `chmod 755`. Observed scope is explicit absolute selection on macOS. Windows, PATH discovery, a real adb installation, connected-device operations, and MCP transport were not tested. ### REA version `rea-agents` 6.7.0, source baseline `9d8e7803326a382cbbb3ffdb900f5e93e5442d68`. Fetched and checked `origin/main` at `7dd6941393c852a3324cf01c2bd79a9dcff43728`: no intervening commits change the cited contract, documentation, ADB configuration/provider/CLI/contract files, or shared configuration-refusal helper. Runtime reproduction was repeated at the baseline; current main was checked through source history, not separately built or executed. ### Runtime and platform Node.js v26.12.0; macOS 27.0.1; arm64. ### Target and artifact context A local empty directory and an inert shell script with mode 0644, both selected through absolute `REA_ADB_PATH` values. Isolated HOME, XDG directories, and temporary directory. No analysis target or Android device. ### Interface CLI ### Earliest failure stage Setup or provider admission ### Relevant output or evidence Both unusable-path invocations return this stdout with exit 1 and empty stderr: ```json {"code":"capability_unavailable","category":"unsupported_provider","message":"The selected adb binary did not report a usable version.","retryable":false,"remediation":{"action":"The selected adb binary did not report a usable version."},"details":{"provider_id":"adb","operation":"inspect_adb_client","reason":"The selected adb binary did not report a usable version."}} ``` The independent verifier's direct process probes returned `EACCES` for both fixtures and confirmed that the internal configuration failure retained the selected path and error code. The public refusal above loses both. Evidence provenance: observed; local verification: independently reproduced and repeated by the submitter. These fixture controls do not verify a real adb installation. ### Typed outcome or recovery expected An actionable unavailable-client refusal preserving the selected path and execution reason. Do not imply that the path was missing or that a running adb returned unusable version output. Keep missing-path and executable-client controls working. Repeating these same controls after a fix is the proposed restoration check; no fix has been tested. ### Analysis or suspected cause Source-derived reasoning: [AdbConfiguration.ts:164-188](https://github.com/morluto/rea/blob/9d8e7803326a382cbbb3ffdb900f5e93e5442d68/src/adb/AdbConfiguration.ts#L164-L188) handles ENOENT separately, but maps EACCES to `version_unresolved` with generic version wording while retaining `selected_binary` and `exit_code`. [providerConfigurationRefusal.ts:12-20](https://github.com/morluto/rea/blob/9d8e7803326a382cbbb3ffdb900f5e93e5442d68/src/domain/providerConfigurationRefusal.ts#L12-L20) projects only the message and optional remediation; these failures provide no remediation. This agrees with the observed CLI result. No bundled dependency was identified as the root cause. ### Additional context Still reproduces after #1952, whose missing/relative-path fix is present in the baseline via merged #1954 (`39418ea173763ca55d4f116992ee903bcaeb1898`). A [comment on the closed issue](https://github.com/morluto/rea/issues/1952#issuecomment-6113613972) also noted the remaining directory/non-executable triggers. This report isolates that unresolved behavior; it does not claim a known-good version or a later reintroduction. Related #5177 and open PR #5180 address Apktool's non-executable launcher being called missing; #5401 addresses objdump artifact acquisition. Their adapter paths and restoration signals differ. Closed #3886 covers ADB timeout identity; #3347 and #3337 cover Apktool deadlines and lifecycle behavior. None establishes restoration of this ADB execution-refusal diagnostic. Prepared with AI assistance.
Author
Owner

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

Cross-referencing with canonical issue #3369 (ADB push reports checksum capture overflow as device unavailability) and sibling Android reports #5093, #5190, #5690.

Consolidated under Cluster AH (Android ADB Automation & Activity Execution Boundaries) in tracker #4330.

<!-- gh-comment-id:6304475213 --> @matbrgz commented on GitHub (Oct 20, 2026): Cross-referencing with canonical issue #3369 (`ADB push reports checksum capture overflow as device unavailability`) and sibling Android reports #5093, #5190, #5690. Consolidated under **Cluster AH (Android ADB Automation & Activity Execution Boundaries)** in tracker #4330.
Author
Owner

@chordpli commented on GitHub (Oct 21, 2026):

I'd like to take this one.

Repro (current main d7ca93cc2, built CLI, macOS)

  • REA_ADB_PATH set to a directory: exit 1, capability_unavailable, "did not report a usable version"
  • REA_ADB_PATH set to a file without execute permission: same result
  • Missing path (control): the message names the path and REA_ADB_PATH
  • Real adb 37.0.1 (control): succeeds

Cause
inspectAdbClient (src/adb/AdbConfiguration.ts) maps only ENOENT to binary_missing. An EACCES/EPERM spawn error falls through to the generic version_unresolved branch, which also drops path_source. None of these diagnostics reach the public details.

Plan

  • Classify EACCES/EPERM spawn errors as a separate configuration failure. Readiness stays refused.
  • Report the selected path, REA_ADB_PATH when the path comes from the environment, and the errno.
  • Remediation: check the execute permission, and point REA_ADB_PATH at the adb executable, not a directory.
  • Missing-path, unrecognized-version and success behavior stay unchanged.
  • Add CLI-boundary regression tests for the directory, non-executable file, missing path and executable cases, then re-run the E2E with a real adb.
<!-- gh-comment-id:6328995108 --> @chordpli commented on GitHub (Oct 21, 2026): I'd like to take this one. **Repro** (current main `d7ca93cc2`, built CLI, macOS) - `REA_ADB_PATH` set to a directory: exit 1, `capability_unavailable`, "did not report a usable version" - `REA_ADB_PATH` set to a file without execute permission: same result - Missing path (control): the message names the path and `REA_ADB_PATH` - Real adb 37.0.1 (control): succeeds **Cause** `inspectAdbClient` (`src/adb/AdbConfiguration.ts`) maps only `ENOENT` to `binary_missing`. An `EACCES`/`EPERM` spawn error falls through to the generic `version_unresolved` branch, which also drops `path_source`. None of these diagnostics reach the public `details`. **Plan** - Classify `EACCES`/`EPERM` spawn errors as a separate configuration failure. Readiness stays refused. - Report the selected path, `REA_ADB_PATH` when the path comes from the environment, and the errno. - Remediation: check the execute permission, and point `REA_ADB_PATH` at the adb executable, not a directory. - Missing-path, unrecognized-version and success behavior stay unchanged. - Add CLI-boundary regression tests for the directory, non-executable file, missing path and executable cases, then re-run the E2E with a real adb.
Author
Owner

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

Checked resolved on main at d87e73f2db.

I replayed the compiled CLI with an inert selected-adb matrix. A directory and 0644 file both exit 1 with capability_unavailable, the selected path, path_source: "environment", filesystem_error: "EACCES", and REA_ADB_PATH execute/file-type guidance. Missing-path advice remains distinct. The executable control exits 0 with its expected version and contacted_adb_server: false; unrecognized output is classified separately. No real adb server or device was contacted.

Relevant implementation: AdbConfiguration.ts, AdbConfiguration.ts.

Closing as completed on main.

<!-- gh-comment-id:6380754824 --> @coygeek commented on GitHub (Oct 24, 2026): Checked resolved on `main` at d87e73f2db50be72d33a4b3c7199af35518b441c. I replayed the compiled CLI with an inert selected-adb matrix. A directory and 0644 file both exit 1 with `capability_unavailable`, the selected path, `path_source: "environment"`, `filesystem_error: "EACCES"`, and `REA_ADB_PATH` execute/file-type guidance. Missing-path advice remains distinct. The executable control exits 0 with its expected version and `contacted_adb_server: false`; unrecognized output is classified separately. No real adb server or device was contacted. Relevant implementation: [AdbConfiguration.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/src/adb/AdbConfiguration.ts#L177), [AdbConfiguration.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/src/adb/AdbConfiguration.ts#L166). 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#3441
No description provided.