[GH-ISSUE #2675] fix(snapshot): non-object JSON roots report file-access failures #977

Closed
opened 2026-10-15 18:30:02 +00:00 by bsakaguchi · 0 comments
Owner

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

Runtime or environment

Source revision a2d8b94dd5, tested with Node 24.18.0 and npm 11.16.0. Verification used the source snapshot reader and production error projection. An installed release and complete CLI/MCP transport were not run. Current upstream recheck at 3ae826ceba confirms the same root-shape rejection and error-classification path in source; no new runtime reproduction was run.

Summary

Selecting a readable snapshot file containing [] rejects the input with execution_failure, reason io, and advice to check file permissions. The file was read successfully; the failure is its non-object root. The same result occurred for null, 5, "x", and true. Clients receive the wrong failure code, and users receive recovery advice unrelated to the input problem.

Steps to reproduce

From a source checkout with its locked dependencies available, save this focused test as src/application/binary/analysisSnapshotRootShape.test.ts:

import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { expect, it } from "vitest";
import { readAnalysisSnapshot } from "./AnalysisSnapshotFiles.js";
import { projectAnalysisError } from "../../domain/analysisErrorProjection.js";

it("reports the classification of a readable non-object snapshot", async () => {
  const directory = await mkdtemp(join(tmpdir(), "snapshot-root-"));
  try {
    const path = join(directory, "snapshot.json");
    await writeFile(path, "[]");
    expect(await readFile(path, "utf8")).toBe("[]");
    const result = await readAnalysisSnapshot(path);
    if (result.ok) throw new Error("Expected snapshot rejection");
    const error = projectAnalysisError(result.error);
    console.log(JSON.stringify({
      code: error.code,
      message: error.message,
      reason: error.details?.reason,
    }));
    expect(error.code).toBe("execution_failure");
    expect(error.details?.reason).toBe("io");
  } finally {
    await rm(directory, { recursive: true, force: true });
  }
});

Run the source test:

node scripts/run-development-tests.mjs focused src/application/binary/analysisSnapshotRootShape.test.ts

The locally executed test used these reader/projection calls through a serialized source-test launcher, with additional scalar and control cases. The assertions above capture the current faulty result. The supported user entry points are MCP open_binary with absolute path and snapshot_path, or CLI rea analyze for a binary with --snapshot. Public-entry-point reachability was traced in source, not executed through their transports.

Expected behavior

Reject a readable array or scalar as an invalid snapshot document. The machine-readable result and remediation should identify an input/structure problem rather than inability to access the file. Snapshot content validation must continue to reject malformed documents, and actual file-access failures must remain distinguishable.

Actual behavior

The directly observed projection for the two-byte array file was:

{
  "code": "execution_failure",
  "message": "Evidence file could not be accessed. Check file permissions and try again.",
  "reason": "io"
}

The preserved cause identified the actual problem as JSON document root must be an object. All five tested non-object roots produced the same code, access message and reason. The malformed syntax control [ returned evidence_integrity_mismatch with invalid-json; the object {} returned an integrity error for missing snapshot members. A valid serialized object snapshot loaded successfully, and its input bytes remained unchanged.

Evidence

  • Expected source: docs/cli.md:156 documents snapshot loading and reuse. src/application/binary/AnalysisSnapshotFiles.ts:25 validates the selected snapshot and distinguishes structural validation failures. src/domain/analysisErrorProjection.ts:157 distinguishes invalid-json from io, and src/domain/analysisErrorPresentation.ts:422 assigns different recovery advice to JSON and access failures.
  • Failure source: The focused source test directly reproduced the result through readAnalysisSnapshot and projectAnalysisError. The observed projection and preserved root-shape cause are recorded above. Relevant boundary locators are src/application/JsonInputFile.ts:81 and src/application/JsonFiles.ts:115.
  • Evidence provenance: observed
  • Local verification: reproduced
  • Reproduction completeness: complete

Related: #1680 concerns large-snapshot import capacity; #2050 concerns selecting one Evidence record where a bundle is expected; #2152 concerns client-configuration shape diagnostics. Each has a distinct failed contract.

Restoration check

Repeat the readable [] case and require a snapshot input/structure rejection with useful recovery advice, without reason io or the permissions message. Check that the scalar cases behave consistently. Retain the syntax-error and missing-members rejections and successful valid-object loading. A separate actual access-failure control should retain its access classification; that control was not run during this investigation.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: A supported snapshot-loading request receives an incorrect machine-readable failure code and misleading recovery advice for readable but structurally invalid input. The defect is bounded to rejection reporting; the valid snapshot control loaded and preserved its input.
  • Workaround status: available
  • Workaround basis: Select or regenerate a valid object snapshot instead of the array or scalar document. The focused control demonstrated successful loading of a valid object snapshot without source changes.
Originally created by @coygeek on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2675 ## Runtime or environment Source revision a2d8b94dd50dab8d966239dd63ab84718aa8b4b4, tested with Node 24.18.0 and npm 11.16.0. Verification used the source snapshot reader and production error projection. An installed release and complete CLI/MCP transport were not run. Current upstream recheck at 3ae826ceba6f25b08bce50bcb51001209bc16b57 confirms the same root-shape rejection and error-classification path in source; no new runtime reproduction was run. ## Summary Selecting a readable snapshot file containing `[]` rejects the input with `execution_failure`, reason `io`, and advice to check file permissions. The file was read successfully; the failure is its non-object root. The same result occurred for `null`, `5`, `"x"`, and `true`. Clients receive the wrong failure code, and users receive recovery advice unrelated to the input problem. ## Steps to reproduce From a source checkout with its locked dependencies available, save this focused test as `src/application/binary/analysisSnapshotRootShape.test.ts`: ```ts import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { expect, it } from "vitest"; import { readAnalysisSnapshot } from "./AnalysisSnapshotFiles.js"; import { projectAnalysisError } from "../../domain/analysisErrorProjection.js"; it("reports the classification of a readable non-object snapshot", async () => { const directory = await mkdtemp(join(tmpdir(), "snapshot-root-")); try { const path = join(directory, "snapshot.json"); await writeFile(path, "[]"); expect(await readFile(path, "utf8")).toBe("[]"); const result = await readAnalysisSnapshot(path); if (result.ok) throw new Error("Expected snapshot rejection"); const error = projectAnalysisError(result.error); console.log(JSON.stringify({ code: error.code, message: error.message, reason: error.details?.reason, })); expect(error.code).toBe("execution_failure"); expect(error.details?.reason).toBe("io"); } finally { await rm(directory, { recursive: true, force: true }); } }); ``` Run the source test: ```bash node scripts/run-development-tests.mjs focused src/application/binary/analysisSnapshotRootShape.test.ts ``` The locally executed test used these reader/projection calls through a serialized source-test launcher, with additional scalar and control cases. The assertions above capture the current faulty result. The supported user entry points are MCP `open_binary` with absolute `path` and `snapshot_path`, or CLI `rea analyze` for a binary with `--snapshot`. Public-entry-point reachability was traced in source, not executed through their transports. ## Expected behavior Reject a readable array or scalar as an invalid snapshot document. The machine-readable result and remediation should identify an input/structure problem rather than inability to access the file. Snapshot content validation must continue to reject malformed documents, and actual file-access failures must remain distinguishable. ## Actual behavior The directly observed projection for the two-byte array file was: ```json { "code": "execution_failure", "message": "Evidence file could not be accessed. Check file permissions and try again.", "reason": "io" } ``` The preserved cause identified the actual problem as `JSON document root must be an object`. All five tested non-object roots produced the same code, access message and reason. The malformed syntax control `[` returned `evidence_integrity_mismatch` with `invalid-json`; the object `{}` returned an integrity error for missing snapshot members. A valid serialized object snapshot loaded successfully, and its input bytes remained unchanged. ## Evidence - Expected source: `docs/cli.md:156` documents snapshot loading and reuse. `src/application/binary/AnalysisSnapshotFiles.ts:25` validates the selected snapshot and distinguishes structural validation failures. `src/domain/analysisErrorProjection.ts:157` distinguishes `invalid-json` from `io`, and `src/domain/analysisErrorPresentation.ts:422` assigns different recovery advice to JSON and access failures. - Failure source: The focused source test directly reproduced the result through `readAnalysisSnapshot` and `projectAnalysisError`. The observed projection and preserved root-shape cause are recorded above. Relevant boundary locators are `src/application/JsonInputFile.ts:81` and `src/application/JsonFiles.ts:115`. - Evidence provenance: observed - Local verification: reproduced - Reproduction completeness: complete Related: #1680 concerns large-snapshot import capacity; #2050 concerns selecting one Evidence record where a bundle is expected; #2152 concerns client-configuration shape diagnostics. Each has a distinct failed contract. ## Restoration check Repeat the readable `[]` case and require a snapshot input/structure rejection with useful recovery advice, without reason `io` or the permissions message. Check that the scalar cases behave consistently. Retain the syntax-error and missing-members rejections and successful valid-object loading. A separate actual access-failure control should retain its access classification; that control was not run during this investigation. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: A supported snapshot-loading request receives an incorrect machine-readable failure code and misleading recovery advice for readable but structurally invalid input. The defect is bounded to rejection reporting; the valid snapshot control loaded and preserved its input. - Workaround status: available - Workaround basis: Select or regenerate a valid object snapshot instead of the array or scalar document. The focused control demonstrated successful loading of a valid object snapshot without source changes.
bsakaguchi 2026-10-15 18:30:02 +00:00
  • closed this issue
  • added the
    bug
    label
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#977
No description provided.