[GH-ISSUE #5844] [Bug] Relative JADX JAR selection is reported as unset and omitted from diagnostics #3541

Closed
opened 2026-10-31 00:41:40 +00:00 by bsakaguchi · 1 comment
Owner

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

Originally assigned to: @kaoru0822-kitauji on GitHub.

Before submitting

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

Area

Setup, packaging, or upgrade

Observed behavior

With REA_JADX_MCP_JAR=./tools/jadx-headless-mcp-0.7.1-all.jar, the public inspect-android-package CLI returns capability_unavailable with details.diagnostics.jar_configured: false and failure_code: "not_configured". The selected value is absent from the result. Unsetting the variable produces byte-identical stdout.

The refusal correctly requires an absolute path, and its message states that requirement. The defect is that callers cannot distinguish an omitted setting from a supplied value that failed validation or inspect the value REA rejected.

Reproduction

Run from the built baseline checkout with dependencies installed. Set VERIFY_SCRATCH to an empty isolated directory outside the checkout, then run the following Python script. It redirects home, configuration, cache, state, data and temporary storage into that directory and passes no ambient REA settings.

import json, os, pathlib, subprocess, zipfile
root = pathlib.Path(os.environ['VERIFY_SCRATCH']).resolve()
root.mkdir(parents=True, exist_ok=True)
env = {'PATH': os.environ['PATH'], 'REA_LOG_LEVEL': 'silent'}
for key in ('HOME', 'XDG_CONFIG_HOME', 'XDG_CACHE_HOME', 'XDG_STATE_HOME', 'XDG_DATA_HOME', 'TMPDIR'):
    directory = root / key.lower()
    directory.mkdir(exist_ok=True)
    env[key] = str(directory)
apk = root / 'sample.apk'
with zipfile.ZipFile(apk, 'w') as z:
    z.writestr('AndroidManifest.xml', '<manifest package="example.verify"/>')
outputs = []
for name, value in [('relative', './tools/jadx-headless-mcp-0.7.1-all.jar'), ('unset', None)]:
    selected = dict(env)
    if value is not None:
        selected['REA_JADX_MCP_JAR'] = value
    run = subprocess.run(['node', 'scripts/rea.mjs', 'inspect-android-package', str(apk), '--format', 'json'], env=selected, text=True, capture_output=True, timeout=40)
    outputs.append(run.stdout)
    error = json.loads(run.stdout)
    print(json.dumps({'case': name, 'exit': run.returncode, 'stderr': run.stderr, 'code': error['code'], 'diagnostics': error['details']['diagnostics']}))
print('byte_identical=' + str(outputs[0] == outputs[1]).lower())

The fixture is a reduced ZIP admitted as APK format, not a functional APK. No JAR or Java installation is needed: refusal occurs before Java selection or engine launch. The initial run and a second run of this portable script both reproduced the relative-versus-unset equivalence.

Expected behavior

Keep rejecting non-absolute JAR selections, but preserve the supplied path and identify the failed absolute-path constraint without reporting that the setting was absent. Preserve the unset case as a distinct condition. The exact diagnostic field names and failure-code spelling can remain an implementation choice.

AGENTS.md requires preserving caller-selected paths and meaningful failure reasons. The Android setup guide shows the absolute JAR selection; accepting relative paths is not requested.

Impact and scope

P3: misleading configuration diagnostics for an already-invalid input. Callers lose the rejected selection and receive the same metadata as an unset variable. The existing message provides the correct recovery: select an absolute JAR path. No wrong analysis result or target execution was observed, and a successful real-engine run was not tested.

Runtime verification covers the CLI on the platform below. MCP, doctor rendering, capability inventory, Windows and Linux were not run. No regression window was established.

REA version

rea-agents 6.7.0; source baseline a5f982de8d

Runtime and platform

Node.js v26.12.0; macOS 27.0.1 arm64; no JAR, JDK or Android device used

Target and artifact context

Synthetic ZIP with an AndroidManifest.xml entry and .apk suffix, used only for provider admission; no Android analysis ran

Interface

CLI

Earliest failure stage

Setup or provider admission

Relevant output or evidence

Portable script output, captured from the public CLI:

{"case": "relative", "exit": 1, "stderr": "", "code": "capability_unavailable", "diagnostics": {"jar_configured": false, "failure_kind": "jar", "failure_code": "not_configured"}}
{"case": "unset", "exit": 1, "stderr": "", "code": "capability_unavailable", "diagnostics": {"jar_configured": false, "failure_kind": "jar", "failure_code": "not_configured"}}
byte_identical=true

The complete response in both cases contains this message, also repeated as the remediation action and details.reason:

Set REA_JADX_MCP_JAR to the absolute path of a caller-supplied jadx-headless-mcp 0.7.1 JAR. REA does not download or install it.

Typed outcome or recovery expected

No response

Analysis or suspected cause

Source-derived: resolveJar merges undefined and non-absolute values, emitting only jar_configured: false. The configuration failure projection adds the failure kind and code without recovering the discarded path. The production provider calls this resolver before hashing the JAR.

Additional context

Searches of open and closed issues and PRs found no matching report.

Originally created by @coygeek on GitHub (Oct 21, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5844 Originally assigned to: @kaoru0822-kitauji on GitHub. ### 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 Setup, packaging, or upgrade ### Observed behavior With `REA_JADX_MCP_JAR=./tools/jadx-headless-mcp-0.7.1-all.jar`, the public `inspect-android-package` CLI returns `capability_unavailable` with `details.diagnostics.jar_configured: false` and `failure_code: "not_configured"`. The selected value is absent from the result. Unsetting the variable produces byte-identical stdout. The refusal correctly requires an absolute path, and its message states that requirement. The defect is that callers cannot distinguish an omitted setting from a supplied value that failed validation or inspect the value REA rejected. ### Reproduction Run from the built baseline checkout with dependencies installed. Set `VERIFY_SCRATCH` to an empty isolated directory outside the checkout, then run the following Python script. It redirects home, configuration, cache, state, data and temporary storage into that directory and passes no ambient REA settings. ```python import json, os, pathlib, subprocess, zipfile root = pathlib.Path(os.environ['VERIFY_SCRATCH']).resolve() root.mkdir(parents=True, exist_ok=True) env = {'PATH': os.environ['PATH'], 'REA_LOG_LEVEL': 'silent'} for key in ('HOME', 'XDG_CONFIG_HOME', 'XDG_CACHE_HOME', 'XDG_STATE_HOME', 'XDG_DATA_HOME', 'TMPDIR'): directory = root / key.lower() directory.mkdir(exist_ok=True) env[key] = str(directory) apk = root / 'sample.apk' with zipfile.ZipFile(apk, 'w') as z: z.writestr('AndroidManifest.xml', '<manifest package="example.verify"/>') outputs = [] for name, value in [('relative', './tools/jadx-headless-mcp-0.7.1-all.jar'), ('unset', None)]: selected = dict(env) if value is not None: selected['REA_JADX_MCP_JAR'] = value run = subprocess.run(['node', 'scripts/rea.mjs', 'inspect-android-package', str(apk), '--format', 'json'], env=selected, text=True, capture_output=True, timeout=40) outputs.append(run.stdout) error = json.loads(run.stdout) print(json.dumps({'case': name, 'exit': run.returncode, 'stderr': run.stderr, 'code': error['code'], 'diagnostics': error['details']['diagnostics']})) print('byte_identical=' + str(outputs[0] == outputs[1]).lower()) ``` The fixture is a reduced ZIP admitted as APK format, not a functional APK. No JAR or Java installation is needed: refusal occurs before Java selection or engine launch. The initial run and a second run of this portable script both reproduced the relative-versus-unset equivalence. ### Expected behavior Keep rejecting non-absolute JAR selections, but preserve the supplied path and identify the failed absolute-path constraint without reporting that the setting was absent. Preserve the unset case as a distinct condition. The exact diagnostic field names and failure-code spelling can remain an implementation choice. [AGENTS.md requires preserving caller-selected paths and meaningful failure reasons](https://github.com/morluto/rea/blob/a5f982de8dbe4b092cc20ab89d492b7e7028b758/AGENTS.md#L13-L31). [The Android setup guide shows the absolute JAR selection](https://github.com/morluto/rea/blob/a5f982de8dbe4b092cc20ab89d492b7e7028b758/docs/android-analysis.md#L71-L79); accepting relative paths is not requested. ### Impact and scope P3: misleading configuration diagnostics for an already-invalid input. Callers lose the rejected selection and receive the same metadata as an unset variable. The existing message provides the correct recovery: select an absolute JAR path. No wrong analysis result or target execution was observed, and a successful real-engine run was not tested. Runtime verification covers the CLI on the platform below. MCP, doctor rendering, capability inventory, Windows and Linux were not run. No regression window was established. ### REA version rea-agents 6.7.0; source baseline a5f982de8dbe4b092cc20ab89d492b7e7028b758 ### Runtime and platform Node.js v26.12.0; macOS 27.0.1 arm64; no JAR, JDK or Android device used ### Target and artifact context Synthetic ZIP with an AndroidManifest.xml entry and .apk suffix, used only for provider admission; no Android analysis ran ### Interface CLI ### Earliest failure stage Setup or provider admission ### Relevant output or evidence Portable script output, captured from the public CLI: ```text {"case": "relative", "exit": 1, "stderr": "", "code": "capability_unavailable", "diagnostics": {"jar_configured": false, "failure_kind": "jar", "failure_code": "not_configured"}} {"case": "unset", "exit": 1, "stderr": "", "code": "capability_unavailable", "diagnostics": {"jar_configured": false, "failure_kind": "jar", "failure_code": "not_configured"}} byte_identical=true ``` The complete response in both cases contains this message, also repeated as the remediation action and `details.reason`: ```text Set REA_JADX_MCP_JAR to the absolute path of a caller-supplied jadx-headless-mcp 0.7.1 JAR. REA does not download or install it. ``` ### Typed outcome or recovery expected _No response_ ### Analysis or suspected cause Source-derived: [resolveJar merges undefined and non-absolute values](https://github.com/morluto/rea/blob/a5f982de8dbe4b092cc20ab89d492b7e7028b758/src/android/JadxConfiguration.ts#L543-L553), emitting only `jar_configured: false`. [The configuration failure projection](https://github.com/morluto/rea/blob/a5f982de8dbe4b092cc20ab89d492b7e7028b758/src/android/JadxConfiguration.ts#L293-L310) adds the failure kind and code without recovering the discarded path. [The production provider calls this resolver before hashing the JAR](https://github.com/morluto/rea/blob/a5f982de8dbe4b092cc20ab89d492b7e7028b758/src/android/JadxProvider.ts#L435-L450). ### Additional context Searches of open and closed issues and PRs found no matching report.
Author
Owner

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

Agreed — byte-identical output for "unset" vs "supplied but non-absolute" makes automation unable to tell a missing configuration from a rejected one, which is exactly the failure-reason-preservation AGENTS.md asks for. Keeping the unset case as its own distinct condition (e.g. a not_set vs invalid_value failure code) while echoing the rejected path in diagnostics would preserve caller intent and make the recovery actionable. The absolute-path requirement itself is fine to keep.

<!-- gh-comment-id:6311880117 --> @XinwangTao commented on GitHub (Oct 21, 2026): Agreed — byte-identical output for "unset" vs "supplied but non-absolute" makes automation unable to tell a missing configuration from a rejected one, which is exactly the failure-reason-preservation AGENTS.md asks for. Keeping the unset case as its own distinct condition (e.g. a not_set vs invalid_value failure code) while echoing the rejected path in diagnostics would preserve caller intent and make the recovery actionable. The absolute-path requirement itself is fine to keep.
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#3541
No description provided.