[GH-ISSUE #7573] [Bug] Evidence export reports a file-size constraint as a permission failure #4512

Closed
opened 2026-10-31 00:50:24 +00:00 by bsakaguchi · 0 comments
Owner

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

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

node scripts/rea.mjs evidence-export SOURCE OUTPUT --format json fails under an inherited file-size limit with code and category both execution_failure, details.reason: io, and the instruction “Evidence file could not be accessed. Check file permissions and try again.” The projected error does not identify the file-size constraint or its system code.

A direct filesystem control under the same limit returned EFBIG. Retrying the export with the same input and destination outside the limited subshell succeeded. The failed export preserved its input, left the destination absent, and removed its staging directory.

Reproduction

  1. Use the built baseline checkout with Node.js v24.22.1 on PATH. Run the following with Bash; TMPDIR must name an existing writable disposable parent. The fixture is a 16-byte safetensors file containing an empty JSON header. The first command produces a valid Evidence bundle larger than the subsequent file-size limit.
  2. Observe the limited export's exit 1 and permissions advice, followed by successful publication at the identical destination when the limit is absent. Only the limited subshell ignores SIGXFSZ. The EXIT trap removes the fixture and all output.
case_dir="$(mktemp -d "${TMPDIR%/}/rea-storage.XXXXXX")"
trap 'rm -rf "$case_dir"' EXIT
mkdir -p "$case_dir/home" "$case_dir/config" "$case_dir/data" \
  "$case_dir/cache" "$case_dir/state" "$case_dir/temp"
export HOME="$case_dir/home" XDG_CONFIG_HOME="$case_dir/config" \
  XDG_DATA_HOME="$case_dir/data" XDG_CACHE_HOME="$case_dir/cache" \
  XDG_STATE_HOME="$case_dir/state" TMPDIR="$case_dir/temp"
python3 - "$case_dir/model.safetensors" <<'PYFIXTURE'
import struct, sys
with open(sys.argv[1], 'wb') as f:
    f.write(struct.pack('<Q', 8) + b'{}      ')
PYFIXTURE
node scripts/rea.mjs inspect-model-artifact "$case_dir/model.safetensors" \
  --detail summary --evidence_output "$case_dir/bundle.json" --format json > /dev/null
printf 'bundle generation exit=%s\n' "$?"
source_hash="$(shasum -a 256 "$case_dir/bundle.json" | cut -d ' ' -f 1)"
wc -c < "$case_dir/bundle.json"
( trap '' XFSZ; ulimit -f 1
  node scripts/rea.mjs evidence-export "$case_dir/bundle.json" \
    "$case_dir/out.json" --format json
  printf 'limited export exit=%s\n' "$?"
)
test ! -e "$case_dir/out.json" && echo 'limited output absent'
find "$case_dir" -name '.rea-write-*' -print
node scripts/rea.mjs evidence-export "$case_dir/bundle.json" \
  "$case_dir/out.json" --format json
printf 'unrestricted export exit=%s\n' "$?"
test -s "$case_dir/out.json" && echo 'unrestricted output exists'
test "$source_hash" = "$(shasum -a 256 "$case_dir/bundle.json" | cut -d ' ' -f 1)" \
  && echo 'source SHA-256 unchanged'

The limited export reproduced in two initial executions and both confirmation executions. The final explicit-parent confirmation produced a 2,468-byte bundle; its size varies with the paths recorded inside it. Both unrestricted confirmation exports exited 0. No real filesystem was filled.

Expected behavior

Identify the known host file-size refusal as a resource constraint, preserve the relevant system condition, and direct recovery to the inherited allowance. Checking permissions cannot resolve this refusal. Preserve the existing safe behavior: no partial destination and complete staging cleanup.

The project's user-visible error catalog calls for reason-specific plain messages with safe recovery. Its tagged resource-error contract distinguishes measured constraints, and its private-workspace error handling already preserves file-size and storage failures as resource constraints. Exact sources are listed below.

Impact and scope

P2: the machine-readable result hides a known resource constraint and supplies recovery advice unrelated to the cause. This is a bounded failure-reporting defect. A safe workaround was demonstrated: the identical export succeeded once it ran without the restrictive inherited limit. No source corruption, published partial file, or retained staging directory was observed.

inspect-model-artifact MODEL --detail summary --evidence_output OUTPUT --format json also returned the same code/category/message/reason when run once under the limit. That error retained partial_observation; it still omitted the host file-size condition. The destination remained absent and staging was removed.

Runtime coverage is macOS and real file-size refusal. Disk-full, quota exhaustion, other operating systems, MCP and separately installed package behavior were not executed. Natural occurrence frequency is unknown.

REA version

Exact node scripts/rea.mjs --version output:

6.8.0

Source baseline: 65f1c447344a423fa2785847dbcea1e9a9e2454a.

Runtime and platform

Node.js v24.22.1; macOS 27.0.1; arm64. Bash supplies the subshell file-size limit. No external analysis provider is required.

Target and artifact context

An inline safetensors empty-header fixture and the valid Evidence JSON generated from it. The export destination is a fresh regular-file name under a writable local directory.

Interface

CLI

Earliest failure stage

Artifact or evidence registration

Relevant output or evidence

Selected complete fields from an executed limited export, with only the generated destination path normalized:

{
  "error": "Analysis failed",
  "code": "execution_failure",
  "category": "execution_failure",
  "message": "Evidence file could not be accessed. Check file permissions and try again.",
  "retryable": false,
  "remediation": {
    "action": "Evidence file could not be accessed. Check file permissions and try again."
  },
  "details": {
    "operation": "write",
    "reason": "io",
    "path": "<case_dir>/out.json"
  }
}

The raw filesystem control used node -e to call fs.writeFileSync with a 2,048-byte buffer under the same trap '' XFSZ; ulimit -f 1 subshell settings. Its caught error printed {"code":"EFBIG","syscall":"write"}. The final export control printed a success receipt with bytes: 2468 and records: 1. The source SHA-256 stayed unchanged.

Baseline contract and failure locators:

  • docs/user-visible-errors.csv:16: EvidenceFileError entry, harm_rank 12, specifies reason-specific plain messages with safe recovery.
  • AGENTS.md, Architecture and Cleanup: preserve meaningful failure reasons at unknown boundaries.
  • src/domain/analysisErrorCore.ts:24-60: resource kinds and measured-resource error contract.
  • src/process/privateWorkspaceFailure.ts:28-60: source comparison; ENOSPC/EDQUOT/EFBIG become resource constraints with system code and path. This helper is used by pcap, TShark and sigrok; those providers were not run here.
  • src/application/JsonFiles.ts:440-466: host write errors become EvidenceFileError and EFBIG takes the generic io fallback.
  • src/domain/analysisErrorPresentation.ts:225-240,523-542: Evidence path-limit receives a resource category; io receives generic execution failure and permission advice.
  • src/domain/analysisErrorProjection.ts:409-432: Evidence error details project the operation, reason and path without the host errno.

Typed outcome or recovery expected

A resource-constraint result identifying the actual file-size refusal and applicable inherited-limit recovery. Keep destination preservation and cleanup unchanged. Repeating the command under the same inadequate allowance should continue to fail safely.

Analysis or suspected cause

Source-derived: the shared writer distinguishes missing paths and pathname-length limits but collapses EFBIG into io. The error presentation then selects permission-oriented text, and the public projection omits the host cause. ENOSPC and EDQUOT would also take that fallback if raised there; these additional conditions were not reproduced.

Additional context

Duplicate checks covered open and closed issues, open and merged PRs, and issue comments using the exact message, EFBIG, ENOSPC, export/resource, permissions, disk-full and quota queries. No matching report or fix was found.

Related reports have different restoration conditions: #6033 covers rollback retry, #5408 covers unavailable overwrite advice, #5480 covers long-path staging, and #4176 covers firmware publication deadlines. #6123 and merged PR #6229 classify provider-private workspace errors; they do not change the Evidence writer. Merged PR #1074 fixes missing paths and leaves other I/O on the generic fallback. No regression from these fixes is claimed.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: A real host file-size refusal becomes a generic execution failure with no host condition and permission-only recovery, preventing callers from identifying the resource correction from the structured result. Publication and cleanup remain safe.
  • Workaround status: available
  • Workaround basis: Unrestricted retries of the identical export with the same source and destination succeeded; providing a sufficient inherited file-size allowance preserves the requested result.
Originally created by @coygeek on GitHub (Oct 27, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/7573 ### 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 `node scripts/rea.mjs evidence-export SOURCE OUTPUT --format json` fails under an inherited file-size limit with `code` and `category` both `execution_failure`, `details.reason: io`, and the instruction “Evidence file could not be accessed. Check file permissions and try again.” The projected error does not identify the file-size constraint or its system code. A direct filesystem control under the same limit returned `EFBIG`. Retrying the export with the same input and destination outside the limited subshell succeeded. The failed export preserved its input, left the destination absent, and removed its staging directory. ### Reproduction 1. Use the built baseline checkout with Node.js v24.22.1 on PATH. Run the following with Bash; `TMPDIR` must name an existing writable disposable parent. The fixture is a 16-byte safetensors file containing an empty JSON header. The first command produces a valid Evidence bundle larger than the subsequent file-size limit. 2. Observe the limited export's exit 1 and permissions advice, followed by successful publication at the identical destination when the limit is absent. Only the limited subshell ignores SIGXFSZ. The EXIT trap removes the fixture and all output. ```sh case_dir="$(mktemp -d "${TMPDIR%/}/rea-storage.XXXXXX")" trap 'rm -rf "$case_dir"' EXIT mkdir -p "$case_dir/home" "$case_dir/config" "$case_dir/data" \ "$case_dir/cache" "$case_dir/state" "$case_dir/temp" export HOME="$case_dir/home" XDG_CONFIG_HOME="$case_dir/config" \ XDG_DATA_HOME="$case_dir/data" XDG_CACHE_HOME="$case_dir/cache" \ XDG_STATE_HOME="$case_dir/state" TMPDIR="$case_dir/temp" python3 - "$case_dir/model.safetensors" <<'PYFIXTURE' import struct, sys with open(sys.argv[1], 'wb') as f: f.write(struct.pack('<Q', 8) + b'{} ') PYFIXTURE node scripts/rea.mjs inspect-model-artifact "$case_dir/model.safetensors" \ --detail summary --evidence_output "$case_dir/bundle.json" --format json > /dev/null printf 'bundle generation exit=%s\n' "$?" source_hash="$(shasum -a 256 "$case_dir/bundle.json" | cut -d ' ' -f 1)" wc -c < "$case_dir/bundle.json" ( trap '' XFSZ; ulimit -f 1 node scripts/rea.mjs evidence-export "$case_dir/bundle.json" \ "$case_dir/out.json" --format json printf 'limited export exit=%s\n' "$?" ) test ! -e "$case_dir/out.json" && echo 'limited output absent' find "$case_dir" -name '.rea-write-*' -print node scripts/rea.mjs evidence-export "$case_dir/bundle.json" \ "$case_dir/out.json" --format json printf 'unrestricted export exit=%s\n' "$?" test -s "$case_dir/out.json" && echo 'unrestricted output exists' test "$source_hash" = "$(shasum -a 256 "$case_dir/bundle.json" | cut -d ' ' -f 1)" \ && echo 'source SHA-256 unchanged' ``` The limited export reproduced in two initial executions and both confirmation executions. The final explicit-parent confirmation produced a 2,468-byte bundle; its size varies with the paths recorded inside it. Both unrestricted confirmation exports exited 0. No real filesystem was filled. ### Expected behavior Identify the known host file-size refusal as a resource constraint, preserve the relevant system condition, and direct recovery to the inherited allowance. Checking permissions cannot resolve this refusal. Preserve the existing safe behavior: no partial destination and complete staging cleanup. The project's user-visible error catalog calls for reason-specific plain messages with safe recovery. Its tagged resource-error contract distinguishes measured constraints, and its private-workspace error handling already preserves file-size and storage failures as resource constraints. Exact sources are listed below. ### Impact and scope P2: the machine-readable result hides a known resource constraint and supplies recovery advice unrelated to the cause. This is a bounded failure-reporting defect. A safe workaround was demonstrated: the identical export succeeded once it ran without the restrictive inherited limit. No source corruption, published partial file, or retained staging directory was observed. `inspect-model-artifact MODEL --detail summary --evidence_output OUTPUT --format json` also returned the same code/category/message/reason when run once under the limit. That error retained `partial_observation`; it still omitted the host file-size condition. The destination remained absent and staging was removed. Runtime coverage is macOS and real file-size refusal. Disk-full, quota exhaustion, other operating systems, MCP and separately installed package behavior were not executed. Natural occurrence frequency is unknown. ### REA version Exact `node scripts/rea.mjs --version` output: ```text 6.8.0 ``` Source baseline: `65f1c447344a423fa2785847dbcea1e9a9e2454a`. ### Runtime and platform Node.js v24.22.1; macOS 27.0.1; arm64. Bash supplies the subshell file-size limit. No external analysis provider is required. ### Target and artifact context An inline safetensors empty-header fixture and the valid Evidence JSON generated from it. The export destination is a fresh regular-file name under a writable local directory. ### Interface CLI ### Earliest failure stage Artifact or evidence registration ### Relevant output or evidence Selected complete fields from an executed limited export, with only the generated destination path normalized: ```json { "error": "Analysis failed", "code": "execution_failure", "category": "execution_failure", "message": "Evidence file could not be accessed. Check file permissions and try again.", "retryable": false, "remediation": { "action": "Evidence file could not be accessed. Check file permissions and try again." }, "details": { "operation": "write", "reason": "io", "path": "<case_dir>/out.json" } } ``` The raw filesystem control used `node -e` to call `fs.writeFileSync` with a 2,048-byte buffer under the same `trap '' XFSZ; ulimit -f 1` subshell settings. Its caught error printed `{"code":"EFBIG","syscall":"write"}`. The final export control printed a success receipt with `bytes: 2468` and `records: 1`. The source SHA-256 stayed unchanged. Baseline contract and failure locators: - `docs/user-visible-errors.csv:16`: EvidenceFileError entry, harm_rank 12, specifies reason-specific plain messages with safe recovery. - `AGENTS.md`, Architecture and Cleanup: preserve meaningful failure reasons at unknown boundaries. - `src/domain/analysisErrorCore.ts:24-60`: resource kinds and measured-resource error contract. - `src/process/privateWorkspaceFailure.ts:28-60`: source comparison; ENOSPC/EDQUOT/EFBIG become resource constraints with system code and path. This helper is used by pcap, TShark and sigrok; those providers were not run here. - `src/application/JsonFiles.ts:440-466`: host write errors become EvidenceFileError and EFBIG takes the generic `io` fallback. - `src/domain/analysisErrorPresentation.ts:225-240,523-542`: Evidence `path-limit` receives a resource category; `io` receives generic execution failure and permission advice. - `src/domain/analysisErrorProjection.ts:409-432`: Evidence error details project the operation, reason and path without the host errno. ### Typed outcome or recovery expected A resource-constraint result identifying the actual file-size refusal and applicable inherited-limit recovery. Keep destination preservation and cleanup unchanged. Repeating the command under the same inadequate allowance should continue to fail safely. ### Analysis or suspected cause Source-derived: the shared writer distinguishes missing paths and pathname-length limits but collapses EFBIG into `io`. The error presentation then selects permission-oriented text, and the public projection omits the host cause. ENOSPC and EDQUOT would also take that fallback if raised there; these additional conditions were not reproduced. ### Additional context Duplicate checks covered open and closed issues, open and merged PRs, and issue comments using the exact message, EFBIG, ENOSPC, export/resource, permissions, disk-full and quota queries. No matching report or fix was found. Related reports have different restoration conditions: [#6033](https://github.com/morluto/rea/issues/6033) covers rollback retry, [#5408](https://github.com/morluto/rea/issues/5408) covers unavailable overwrite advice, [#5480](https://github.com/morluto/rea/issues/5480) covers long-path staging, and [#4176](https://github.com/morluto/rea/issues/4176) covers firmware publication deadlines. [#6123](https://github.com/morluto/rea/issues/6123) and merged [PR #6229](https://github.com/morluto/rea/pull/6229) classify provider-private workspace errors; they do not change the Evidence writer. Merged [PR #1074](https://github.com/morluto/rea/pull/1074) fixes missing paths and leaves other I/O on the generic fallback. No regression from these fixes is claimed. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: A real host file-size refusal becomes a generic execution failure with no host condition and permission-only recovery, preventing callers from identifying the resource correction from the structured result. Publication and cleanup remain safe. - Workaround status: available - Workaround basis: Unrestricted retries of the identical export with the same source and destination succeeded; providing a sufficient inherited file-size allowance preserves the requested result.
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#4512
No description provided.