[GH-ISSUE #5522] [Bug] environment-export reports a later nested-file path-length failure as invalid input #3359

Closed
opened 2026-10-31 00:39:31 +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/5522

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

node scripts/rea.mjs environment-export MANIFEST DIRECTORY --evidence CAPTURE --json admits an absent output directory, writes three bundle files, then reports a later nested-file pathname-limit failure as invalid_request / invalid_input. It blames the directory argument and omits the host cause and absolute failed path. The host correctly refuses the overlong filename; the defect is the diagnostic.

Prepared with AI assistance and independently reproduced by a separate verifier. The submission agent checked upstream history and duplicates; it did not rerun the runtime reproduction.

Reproduction

From the baseline checkout with dependencies and its prebuilt CLI available, put the repository-pinned Node.js v24.18.0 on PATH and run this Python 3 recipe. This is the self-contained recipe executed independently by the verifier. It uses synthetic HAR input and public CLI commands, isolates HOME/XDG/temporary state, and makes no network request. The byte thresholds are specific to the tested host.

import json, os, pathlib, subprocess, tempfile
root=pathlib.Path(tempfile.mkdtemp(prefix='rea-env-path-')).resolve()
repo=pathlib.Path.cwd()
node='node'
env={'PATH':os.environ['PATH'],'NODE_DISABLE_COMPILE_CACHE':'1','REA_LOG_LEVEL':'silent'}
for key in ('HOME','XDG_CONFIG_HOME','XDG_DATA_HOME','XDG_CACHE_HOME','XDG_STATE_HOME','TMPDIR'):
    folder=root/key.lower();folder.mkdir(exist_ok=True);env[key]=str(folder)
def rea(name,*args):
    p=subprocess.run([node,'scripts/rea.mjs',*map(str,args),'--json'],cwd=repo,env=env,capture_output=True,text=True,timeout=60)
    (root/(name+'.stdout')).write_text(p.stdout);(root/(name+'.stderr')).write_text(p.stderr)
    d=json.loads(p.stdout);print(name,p.returncode,d.get('code',d.get('status','ok')))
    return p.returncode,d
har={'log':{'version':'1.2','creator':{'name':'fixture','version':'1.0'},'pages':[],'entries':[{'startedDateTime':'2024-01-01T00:00:00.000Z','time':1,'request':{'method':'GET','url':'http://example.test/api/items','httpVersion':'HTTP/1.1','headers':[],'queryString':[],'cookies':[],'headersSize':-1,'bodySize':0},'response':{'status':200,'statusText':'OK','httpVersion':'HTTP/1.1','headers':[],'cookies':[],'content':{'size':2,'mimeType':'application/json','text':'{}'},'redirectURL':'','headersSize':-1,'bodySize':2},'cache':{},'timings':{'send':0,'wait':1,'receive':0}}]}}
(root/'session.har').write_text(json.dumps(har))
status,capture=rea('capture','inspect-web-network-capture',root/'session.har','har');assert status==0
(root/'capture.json').write_text(json.dumps(capture))
(root/'view.json').write_text(json.dumps({'source':{'kind':'evidence-file','path':str(root/'capture.json')},'view':{'kind':'environment-manifest'}}))
status,manifest=rea('manifest','inspect-analysis-view',root/'view.json');assert status==0
(root/'manifest.json').write_text(json.dumps(manifest))
status,probe=rea('probe','environment-export',root/'manifest.json',root/'probe','--evidence',root/'capture.json');assert status==0
results=[]
for size in (986,976):
    parent=root/str(size);parent.mkdir(exist_ok=True)
    while len(os.fsencode(str(parent)))+201 < size:
        parent/='b'*200;parent.mkdir(exist_ok=True)
    dest=parent/('l'*(size-len(os.fsencode(str(parent)))-1))
    assert len(dest.name)<=255 and len(os.fsencode(str(dest)))==size
    status,data=rea(str(size),'environment-export',root/'manifest.json',dest,'--evidence',root/'capture.json')
    files=sorted(str(p.relative_to(dest)) for p in dest.rglob('*') if p.is_file())
    target=dest/'artifacts/check_example-test/verify.py'
    try:
        with target.open('xb') as f:f.write(b'probe')
        host={'created':True};target.unlink()
    except OSError as e:host={'errno':e.errno,'error':e.strerror,'filename_bytes':len(os.fsencode(e.filename))}
    results.append({'directory_bytes':size,'exit':status,'response':data,'files':files,'direct_host_probe':host})
(root/'results.json').write_text(json.dumps(results,indent=2))
short=pathlib.Path(results[1]['response']['directory'])
for file in results[1]['response']['files']:
    assert (short/file['path']).stat().st_size == file['bytes']
    assert (short/file['path']).read_bytes() == (root/'probe'/file['path']).read_bytes()
print(json.dumps([{k:row[k] for k in ('directory_bytes','exit','files','direct_host_probe')} for row in results],indent=2))

Capture inspection, manifest projection and the short export exited 0. The canonical 986-byte destination failed after three files; the 976-byte destination exported all seven files. The verifier checked each reported byte count and compared every control file byte for byte with the short export. The final recipe was replayed with the same outcomes; broader frequency was not measured.

Expected behavior

After admitting the directory and writing files, report a later host write failure with its pathname-limit cause and failed output path. Preserve the partial folder for inspection. Do not classify it as an invalid-directory argument refusal. Successful creation of a host-uncreatable pathname is not expected.

docs/cli.md:473-481 distinguishes non-writing argument refusals from later host write failures that leave partial output. AGENTS.md, Architecture and Cleanup, requires meaningful failure reasons.

Impact and scope

P3 diagnostic/classification defect on a bounded set of long output directories. The host legitimately refuses the nested file; no data loss or security-boundary crossing was observed. Selecting the demonstrated 976-byte destination exports the same seven files with identical contents. Other platforms and their path limits were not tested.

REA version

6.7.0; source commit 074768901f3cdc8205b61773fb1faf6f6c7b3ca8, using its prebuilt CLI. No separate reproduction against the published npm package was performed.

Runtime and platform

Node.js v24.18.0 (repository pin); macOS arm64; Python 3 for the fixture and path measurements. NOT_ENOUGH_INFO: the verdict does not record the exact macOS release or Python version. No Hopper/Ghidra provider is involved.

Target and artifact context

Synthetic HAR for http://example.test/api/items, projected through the public CLI into an authenticated capture/manifest pair. Agent environment bundle export to absent directories with canonical absolute path lengths of 986 and 976 bytes.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

Selected fields from the verifier’s 986-byte export response (exit 1):

{
  "code": "invalid_request",
  "category": "invalid_input",
  "message": "Could not exclusively create extraction path: artifacts/check_example-test/verify.py",
  "retryable": true,
  "remediation": {"action": "Correct the listed arguments and retry."},
  "details": {
    "operation": "environment-export",
    "issues": [{
      "path": ["directory"],
      "reason": "invalid_value",
      "message": "Could not exclusively create extraction path: artifacts/check_example-test/verify.py"
    }]
  }
}

The partial bundle contained README.md, its environment Dockerfile, and env.toml. The relative filename artifacts/check_example-test/verify.py is 38 bytes; the absolute destination is 1025 bytes including the separating slash. Direct exclusive creation of that exact file failed with host errno 63, File name too long. REA exposed neither that cause nor the absolute failed path. At 976 bytes the same seven-file bundle exported successfully and matched the short export.

Typed outcome or recovery expected

A useful later output-write failure identifying the host pathname constraint and failed output path, with recovery guidance appropriate to selecting a shorter destination and removing partial output before retrying. No particular replacement error code or exact sentence is required. Preserve the existing partial-folder behavior.

Analysis or suspected cause

Source-derived reasoning at the tested revision: src/cli/environmentCommands.ts:218-255 authenticates the pair and invokes export; src/application/environment/environmentBundleWrite.ts:87-117 admits and writes the tree. src/artifacts/SafeOutputTree.ts:183-196 wraps the file-open failure as an artifact path failure with only the relative filename; src/application/environment/environmentExport.ts:305-315 translates it into a directory argument issue. The direct host probe independently corroborates the omitted pathname-limit cause.

Additional context

Upstream main was fetched and checked through c374c2fe7290b914d73d9e27af38b498753ec593. Changes since the baseline in the cited files concern IL2CPP documentation, output filtering and environment listener diagnostics; the bundle writer, nested-file wrapper and export error translation are unchanged. The latest published release was still 6.7.0.

Related #5480 concerns Evidence staging that rejects otherwise host-creatable final paths; this report concerns an actual final nested pathname that the host cannot create. #5457 / PR #5495 concern a file-occupied root; #5458 concerns a write-permission denial. Those fixes do not cover this later pathname-limit diagnostic.

Proposed restoration checks: rerun the 986-byte failure and retain partial output while exposing its host cause and failed path; retain successful short/976-byte exports and genuine occupied/non-empty destination refusals. No fix was tested. NOT_ENOUGH_INFO: no known-good version or regression window was established.

Originally created by @coygeek on GitHub (Oct 20, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5522 ### 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 `node scripts/rea.mjs environment-export MANIFEST DIRECTORY --evidence CAPTURE --json` admits an absent output directory, writes three bundle files, then reports a later nested-file pathname-limit failure as `invalid_request` / `invalid_input`. It blames the `directory` argument and omits the host cause and absolute failed path. The host correctly refuses the overlong filename; the defect is the diagnostic. Prepared with AI assistance and independently reproduced by a separate verifier. The submission agent checked upstream history and duplicates; it did not rerun the runtime reproduction. ### Reproduction From the baseline checkout with dependencies and its prebuilt CLI available, put the repository-pinned Node.js v24.18.0 on PATH and run this Python 3 recipe. This is the self-contained recipe executed independently by the verifier. It uses synthetic HAR input and public CLI commands, isolates HOME/XDG/temporary state, and makes no network request. The byte thresholds are specific to the tested host. ```python import json, os, pathlib, subprocess, tempfile root=pathlib.Path(tempfile.mkdtemp(prefix='rea-env-path-')).resolve() repo=pathlib.Path.cwd() node='node' env={'PATH':os.environ['PATH'],'NODE_DISABLE_COMPILE_CACHE':'1','REA_LOG_LEVEL':'silent'} for key in ('HOME','XDG_CONFIG_HOME','XDG_DATA_HOME','XDG_CACHE_HOME','XDG_STATE_HOME','TMPDIR'): folder=root/key.lower();folder.mkdir(exist_ok=True);env[key]=str(folder) def rea(name,*args): p=subprocess.run([node,'scripts/rea.mjs',*map(str,args),'--json'],cwd=repo,env=env,capture_output=True,text=True,timeout=60) (root/(name+'.stdout')).write_text(p.stdout);(root/(name+'.stderr')).write_text(p.stderr) d=json.loads(p.stdout);print(name,p.returncode,d.get('code',d.get('status','ok'))) return p.returncode,d har={'log':{'version':'1.2','creator':{'name':'fixture','version':'1.0'},'pages':[],'entries':[{'startedDateTime':'2024-01-01T00:00:00.000Z','time':1,'request':{'method':'GET','url':'http://example.test/api/items','httpVersion':'HTTP/1.1','headers':[],'queryString':[],'cookies':[],'headersSize':-1,'bodySize':0},'response':{'status':200,'statusText':'OK','httpVersion':'HTTP/1.1','headers':[],'cookies':[],'content':{'size':2,'mimeType':'application/json','text':'{}'},'redirectURL':'','headersSize':-1,'bodySize':2},'cache':{},'timings':{'send':0,'wait':1,'receive':0}}]}} (root/'session.har').write_text(json.dumps(har)) status,capture=rea('capture','inspect-web-network-capture',root/'session.har','har');assert status==0 (root/'capture.json').write_text(json.dumps(capture)) (root/'view.json').write_text(json.dumps({'source':{'kind':'evidence-file','path':str(root/'capture.json')},'view':{'kind':'environment-manifest'}})) status,manifest=rea('manifest','inspect-analysis-view',root/'view.json');assert status==0 (root/'manifest.json').write_text(json.dumps(manifest)) status,probe=rea('probe','environment-export',root/'manifest.json',root/'probe','--evidence',root/'capture.json');assert status==0 results=[] for size in (986,976): parent=root/str(size);parent.mkdir(exist_ok=True) while len(os.fsencode(str(parent)))+201 < size: parent/='b'*200;parent.mkdir(exist_ok=True) dest=parent/('l'*(size-len(os.fsencode(str(parent)))-1)) assert len(dest.name)<=255 and len(os.fsencode(str(dest)))==size status,data=rea(str(size),'environment-export',root/'manifest.json',dest,'--evidence',root/'capture.json') files=sorted(str(p.relative_to(dest)) for p in dest.rglob('*') if p.is_file()) target=dest/'artifacts/check_example-test/verify.py' try: with target.open('xb') as f:f.write(b'probe') host={'created':True};target.unlink() except OSError as e:host={'errno':e.errno,'error':e.strerror,'filename_bytes':len(os.fsencode(e.filename))} results.append({'directory_bytes':size,'exit':status,'response':data,'files':files,'direct_host_probe':host}) (root/'results.json').write_text(json.dumps(results,indent=2)) short=pathlib.Path(results[1]['response']['directory']) for file in results[1]['response']['files']: assert (short/file['path']).stat().st_size == file['bytes'] assert (short/file['path']).read_bytes() == (root/'probe'/file['path']).read_bytes() print(json.dumps([{k:row[k] for k in ('directory_bytes','exit','files','direct_host_probe')} for row in results],indent=2)) ``` Capture inspection, manifest projection and the short export exited 0. The canonical 986-byte destination failed after three files; the 976-byte destination exported all seven files. The verifier checked each reported byte count and compared every control file byte for byte with the short export. The final recipe was replayed with the same outcomes; broader frequency was not measured. ### Expected behavior After admitting the directory and writing files, report a later host write failure with its pathname-limit cause and failed output path. Preserve the partial folder for inspection. Do not classify it as an invalid-directory argument refusal. Successful creation of a host-uncreatable pathname is not expected. `docs/cli.md:473-481` distinguishes non-writing argument refusals from later host write failures that leave partial output. `AGENTS.md`, Architecture and Cleanup, requires meaningful failure reasons. ### Impact and scope P3 diagnostic/classification defect on a bounded set of long output directories. The host legitimately refuses the nested file; no data loss or security-boundary crossing was observed. Selecting the demonstrated 976-byte destination exports the same seven files with identical contents. Other platforms and their path limits were not tested. ### REA version 6.7.0; source commit `074768901f3cdc8205b61773fb1faf6f6c7b3ca8`, using its prebuilt CLI. No separate reproduction against the published npm package was performed. ### Runtime and platform Node.js v24.18.0 (repository pin); macOS arm64; Python 3 for the fixture and path measurements. NOT_ENOUGH_INFO: the verdict does not record the exact macOS release or Python version. No Hopper/Ghidra provider is involved. ### Target and artifact context Synthetic HAR for `http://example.test/api/items`, projected through the public CLI into an authenticated capture/manifest pair. Agent environment bundle export to absent directories with canonical absolute path lengths of 986 and 976 bytes. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence Selected fields from the verifier’s 986-byte export response (exit 1): ```json { "code": "invalid_request", "category": "invalid_input", "message": "Could not exclusively create extraction path: artifacts/check_example-test/verify.py", "retryable": true, "remediation": {"action": "Correct the listed arguments and retry."}, "details": { "operation": "environment-export", "issues": [{ "path": ["directory"], "reason": "invalid_value", "message": "Could not exclusively create extraction path: artifacts/check_example-test/verify.py" }] } } ``` The partial bundle contained `README.md`, its environment `Dockerfile`, and `env.toml`. The relative filename `artifacts/check_example-test/verify.py` is 38 bytes; the absolute destination is 1025 bytes including the separating slash. Direct exclusive creation of that exact file failed with host errno 63, `File name too long`. REA exposed neither that cause nor the absolute failed path. At 976 bytes the same seven-file bundle exported successfully and matched the short export. ### Typed outcome or recovery expected A useful later output-write failure identifying the host pathname constraint and failed output path, with recovery guidance appropriate to selecting a shorter destination and removing partial output before retrying. No particular replacement error code or exact sentence is required. Preserve the existing partial-folder behavior. ### Analysis or suspected cause Source-derived reasoning at the tested revision: `src/cli/environmentCommands.ts:218-255` authenticates the pair and invokes export; `src/application/environment/environmentBundleWrite.ts:87-117` admits and writes the tree. `src/artifacts/SafeOutputTree.ts:183-196` wraps the file-open failure as an artifact path failure with only the relative filename; `src/application/environment/environmentExport.ts:305-315` translates it into a directory argument issue. The direct host probe independently corroborates the omitted pathname-limit cause. ### Additional context Upstream `main` was fetched and checked through `c374c2fe7290b914d73d9e27af38b498753ec593`. Changes since the baseline in the cited files concern IL2CPP documentation, output filtering and environment listener diagnostics; the bundle writer, nested-file wrapper and export error translation are unchanged. The latest published release was still 6.7.0. Related #5480 concerns Evidence staging that rejects otherwise host-creatable final paths; this report concerns an actual final nested pathname that the host cannot create. #5457 / PR #5495 concern a file-occupied root; #5458 concerns a write-permission denial. Those fixes do not cover this later pathname-limit diagnostic. Proposed restoration checks: rerun the 986-byte failure and retain partial output while exposing its host cause and failed path; retain successful short/976-byte exports and genuine occupied/non-empty destination refusals. No fix was tested. NOT_ENOUGH_INFO: no known-good version or regression window was established.
Author
Owner

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

Cross-referencing with canonical issue #5480 (). Both issues uncover path-length limits and boundary handling in export pipelines ( and ), resulting in misclassified error diagnostics and intermediate staging residue. Cataloged under Cluster AT in consolidation tracker #4330.

<!-- gh-comment-id:6292614916 --> @matbrgz commented on GitHub (Oct 20, 2026): Cross-referencing with canonical issue #5480 (). Both issues uncover path-length limits and boundary handling in export pipelines ( and ), resulting in misclassified error diagnostics and intermediate staging residue. Cataloged under Cluster AT in consolidation tracker #4330.
Author
Owner

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

Additional reproduced trigger (same error translation): two concurrent exports into the same initially empty directory.

Using the valid synthetic capture/manifest pair from the recipe above, start both commands together from the checkout:

mkdir bundle
node scripts/rea.mjs environment-export manifest.json bundle --evidence capture.json --json > first.json &
node scripts/rea.mjs environment-export manifest.json bundle --evidence capture.json --json > second.json &
wait

Repeat with a fresh empty destination because the race is intermittent. Independently reran on REA 6.7.0 at 074768901f3cdc8205b61773fb1faf6f6c7b3ca8, using its prebuilt CLI, Node.js v24.18.0 and macOS arm64. Across ten pairs: ten successes, nine ordinary Output directory is not empty refusals, and one exclusive-create failure (exit 1, empty stderr) with:

{
  "code": "invalid_request",
  "category": "invalid_input",
  "message": "Could not exclusively create extraction path: README.md",
  "retryable": true,
  "remediation": {"action": "Correct the listed arguments and retry."},
  "details": {
    "operation": "environment-export",
    "issues": [{"path": ["directory"], "reason": "invalid_value", "message": "Could not exclusively create extraction path: README.md"}]
  }
}

All ten completed seven-file bundles matched the serial control by relative file set, byte sizes and SHA-256 digests. The refused write should remain refused; the defect is the misleading classification and recovery guidance. Serial exports or separate destinations avoid this race.

Source inspection shows this reaches the same exclusive-open wrapper in src/artifacts/SafeOutputTree.ts:183-196 and output-write error translation in src/application/environment/environmentExport.ts:305-315 as this issue’s path-length case.

<!-- gh-comment-id:6293142877 --> @coygeek commented on GitHub (Oct 20, 2026): Additional reproduced trigger (same error translation): two concurrent exports into the same initially empty directory. Using the valid synthetic capture/manifest pair from the recipe above, start both commands together from the checkout: ```sh mkdir bundle node scripts/rea.mjs environment-export manifest.json bundle --evidence capture.json --json > first.json & node scripts/rea.mjs environment-export manifest.json bundle --evidence capture.json --json > second.json & wait ``` Repeat with a fresh empty destination because the race is intermittent. Independently reran on REA 6.7.0 at `074768901f3cdc8205b61773fb1faf6f6c7b3ca8`, using its prebuilt CLI, Node.js v24.18.0 and macOS arm64. Across ten pairs: ten successes, nine ordinary `Output directory is not empty` refusals, and one exclusive-create failure (exit 1, empty stderr) with: ```json { "code": "invalid_request", "category": "invalid_input", "message": "Could not exclusively create extraction path: README.md", "retryable": true, "remediation": {"action": "Correct the listed arguments and retry."}, "details": { "operation": "environment-export", "issues": [{"path": ["directory"], "reason": "invalid_value", "message": "Could not exclusively create extraction path: README.md"}] } } ``` All ten completed seven-file bundles matched the serial control by relative file set, byte sizes and SHA-256 digests. The refused write should remain refused; the defect is the misleading classification and recovery guidance. Serial exports or separate destinations avoid this race. Source inspection shows this reaches the same exclusive-open wrapper in `src/artifacts/SafeOutputTree.ts:183-196` and output-write error translation in `src/application/environment/environmentExport.ts:305-315` as this issue’s path-length case.
Author
Owner

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

Additional reproduced trigger: extract-artifact (same SafeOutputTree write path).

Independently reproduced on REA 6.7.0 at 074768901f3cdc8205b61773fb1faf6f6c7b3ca8, using its prebuilt CLI, repository-pinned Node.js v24.18.0 and macOS arm64. With HOME, XDG state directories and TMPDIR isolated in a scratch directory, create a valid synthetic ZIP and invoke the public CLI from the checkout:

python3 - <<'PY'
import pathlib, zipfile
pathlib.Path('fixture').mkdir(exist_ok=True)
entry = '/'.join(['d' * 190] * 5) + '/payload.bin'
with zipfile.ZipFile('fixture/long.zip', 'w') as archive:
    archive.writestr(entry, b'x' * 16)
PY
node scripts/rea.mjs extract-artifact fixture/long.zip --json

The 966-byte logical entry exceeds the tested host's path limit once placed under the generated output root. The command exits 1 with empty stderr and:

{
  "code": "artifact_operation_failed",
  "category": "execution_failure",
  "message": "Artifact could not be read or written. Check file access and try again.",
  "retryable": false,
  "details": {"operation": "extract_artifact", "reason": "io"}
}

Neither the failing entry nor ENAMETOOLONG is named; details.detail is absent. A separate host mkdir probe using the same five components returned errno 63, File name too long. A two-component ZIP control extracted successfully, and its 16 output bytes matched the fixture. The host refusal is correct; the missing context is the defect.

Source inspection shows this reaches the same output-tree write error translation through parent-directory creation: src/artifacts/SafeOutputTree.ts:486-489 rethrows the host mkdir error, and src/artifacts/ArtifactOperationFailure.ts:47 reduces it to an unannotated I/O failure. This adds a parent-directory-creation regression case alongside the issue's final-file-open case.

<!-- gh-comment-id:6294788543 --> @coygeek commented on GitHub (Oct 20, 2026): Additional reproduced trigger: `extract-artifact` (same `SafeOutputTree` write path). Independently reproduced on REA 6.7.0 at `074768901f3cdc8205b61773fb1faf6f6c7b3ca8`, using its prebuilt CLI, repository-pinned Node.js v24.18.0 and macOS arm64. With HOME, XDG state directories and TMPDIR isolated in a scratch directory, create a valid synthetic ZIP and invoke the public CLI from the checkout: ```sh python3 - <<'PY' import pathlib, zipfile pathlib.Path('fixture').mkdir(exist_ok=True) entry = '/'.join(['d' * 190] * 5) + '/payload.bin' with zipfile.ZipFile('fixture/long.zip', 'w') as archive: archive.writestr(entry, b'x' * 16) PY node scripts/rea.mjs extract-artifact fixture/long.zip --json ``` The 966-byte logical entry exceeds the tested host's path limit once placed under the generated output root. The command exits 1 with empty stderr and: ```json { "code": "artifact_operation_failed", "category": "execution_failure", "message": "Artifact could not be read or written. Check file access and try again.", "retryable": false, "details": {"operation": "extract_artifact", "reason": "io"} } ``` Neither the failing entry nor `ENAMETOOLONG` is named; `details.detail` is absent. A separate host mkdir probe using the same five components returned errno 63, `File name too long`. A two-component ZIP control extracted successfully, and its 16 output bytes matched the fixture. The host refusal is correct; the missing context is the defect. Source inspection shows this reaches the same output-tree write error translation through parent-directory creation: `src/artifacts/SafeOutputTree.ts:486-489` rethrows the host mkdir error, and `src/artifacts/ArtifactOperationFailure.ts:47` reduces it to an unannotated I/O failure. This adds a parent-directory-creation regression case alongside the issue's final-file-open case.
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#3359
No description provided.