Skip to content

[Bug] Default TOON output crashes with RangeError on a large resource_constraint that --format json returns #4806

Closed

Description

@JayOfTheKeyboard

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

On a large Electron app, analyze-javascript-application stops with a typed resource_constraint (the parent's result capacity is exhausted) that carries a partial observation of about 620 MB. With --format json the caller gets that error. With the default TOON format, rendering it crashes the CLI: Node prints an uncaught RangeError: Invalid string length from the TOON encoder and exits 1, and stdout is empty.

file:///.../node_modules/@toon-format/toon/dist/index.mjs:1906
	return Array.from(encodeLines(input, options)).join("\n");
	                                               ^

RangeError: Invalid string length
    at Array.join (<anonymous>)
    at encode (file:///.../node_modules/@toon-format/toon/dist/index.mjs:1906:49)
    at Module.format (file:///.../node_modules/incur/dist/Formatter.js:32:12)
    at write (file:///.../node_modules/incur/dist/Cli.js:1122:37)
    at serveImpl (file:///.../node_modules/incur/dist/Cli.js:1368:9)
    at async file:///.../scripts/rea.mjs:95:5

Node.js v24.18.0

#1371 fixed this for --format json, which now streams. TOON is the default, and yaml and md take the same path, so the default command still crashes. The same path renders successful results, so a large enough success should crash the same way, but I have only seen it with this error.

Reproduction

The target is Local 9.2.4 for Linux (WP Engine's free WordPress app). Its resources/app.asar is 135 MB with 19,896 entries.

rea analyze-javascript-application ./Local/resources/app.asar > result.toon
echo $?   # 1, after 1,351 s and 3.9 GiB peak RSS; result.toon is empty

rea analyze-javascript-application ./Local/resources/app.asar --format json > result.json
echo $?   # 1, after 1,473 s and 2.8 GiB peak RSS
head -c 200 result.json
# {"error":"JavaScript application analysis failed","code":"resource_constraint","category":"resource_constraint","message":"The parent's result capacity was exhausted after retaining static facts for node_modules/handlebars/dist/handlebars.amd.js; ...
wc -c < result.json   # 620456896

I could not get a small generated input past the limit: twelve generated 1.66 MB files gave the same 320 MB TOON result as six.

Expected behavior

The default format returns the same typed resource_constraint that --format json returns. If the full error cannot be rendered as text, a smaller typed error in the shape --token-count already uses in src/cli/cliResultOutput.ts (formatted size against constants.MAX_STRING_LENGTH, remediation pointing at --format json or --filter-output) would still tell the caller what happened.

Impact and scope

Default CLI runs of analyze-javascript-application on large Electron apps, and likely any command whose output passes about 512 MiB of TOON, YAML or Markdown text. The crash comes at the end, so the user waits through the whole analysis first (22.5 minutes here) and then gets no typed error to act on.

REA version

main at 2cf9c28

Runtime and platform

Node 24.18.0, Fedora 44 x86_64

Target and artifact context

Local 9.2.4+6788 for Linux, unmodified app.asar copied out of /opt/Local/resources.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

A second TOON run with --integrity-policy record-and-continue crashed the same way after 1,675 s and 3.9 GiB peak RSS.

The JSON error reports parent_result_budget_bytes: 2005337492. V8's MAX_STRING_LENGTH is 536,870,888 characters. So the partial observation can fit the parent budget and still be too large to render as one TOON string.

Typed outcome or recovery expected

resource_constraint with resource: memory, the formatted size if it is known, max_string_characters, and a remediation that names --format json.

Analysis or suspected cause

createCliResultOutput in src/cli/cliResultOutput.ts returns false in any format other than json or jsonl unless --full-output is set (line 145), which hands rendering to Incur. Incur's write calls Formatter.format(base, format) on the result or the error (Cli.js:1122 in the trace), which builds the whole TOON document as one string.

Some options, all yours to choose:

  1. Catch a RangeError from that rendering at the CLI boundary and write the typed error. Incur adds cta and --token-limit truncation in the same call, so the catch has to wrap Incur's write or keep those behaviours.
  2. Estimate the size first, as the --token-count branch does with jsonOutputParts, and refuse before formatting. TOON is not the same length as JSON (Discord's result is 137 MB of TOON and 104 MB of JSON), so the estimate would need a margin.
  3. Stream TOON, YAML and Markdown as JSON is streamed.

Additional context

Related: #4797, the unbounded semantic unknowns that make these results so large. I can send a PR for whichever option you prefer.

Activity

  1. added a commit that references this issue on Oct 17, 2026
    fd6da70
  2. morluto commented on Oct 17, 2026

    @morluto
    Owner

    Fixed in fd6da70.

    The executable now recovers a string-capacity failure only after an ordinary command has completed and before delegated stdout begins. It emits a small typed memory constraint in the requested format, with an explicit unknown formatted size, the runtime string limit, original canonical failure identity when known, and JSON/filter remediation. It does not rerun analysis. Normal Incur CTA/token/human formatting remains delegated; destination failures retain ownership and a closed reader keeps quiet exit 141.

    Failure identity is captured once at the logging boundary, including thrown AnalysisError projections; recovery does not re-parse or retain large partial observations.

    Validation: 16 authored formatter controls fail unchanged e103ae0 and pass with the fix. Added human-TOON, closed-reader, destination, command-error, integrity-identity and CTA controls. The initial fix passed 111 distinct focused tests; incoming CommonJS/plist integration added 201 checks. After the subsequent APK locale merge, 41 targeted CLI/MCP/service checks and 40 bounded JSON checks passed on the published tree. Static checks, docs checks and discovery of 1555 test files passed.

    Limits: no 620 MB Electron reproduction or heavy string-limit test ran. The capacity controls inject the formatter exception, rather than claim a large native reproduction. Sentinel/generator protocols retain their own behavior; this handles ordinary REA command results and existing full-error framing. Twelve small CLI inspections before the unrelated upstream rebases preserved identical raw TOON/JSON replies and token estimates; no speedup, cold-cache or large-result memory claim.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions