Skip to content

Bash tool fails with 'Attempted to assign to readonly property' in v1.14.34 #25873

@stephanschielke

Description

@stephanschielke

Description

In v1.14.34+ (Bun 1.3.13), the compiled + minified opencode binary can intermittently fail tool execution with:

TypeError: Attempted to assign to readonly property

This was also reported in #25835.

What we know (verified)

Scenario Result
Run from source (bun run …) ✅ Works
Compiled binary with minify: false ✅ Works
Compiled binary with minify: true (production default) ❌ Intermittent readonly-property TypeError

Additional verified observations:

  • The failure shows up in the full chat/tool-call runtime path (the one that goes through ai.streamText({ tools })).
  • The /session/:sessionID/shell endpoint (direct shell execution) did not reproduce this error for us, even when exercised repeatedly.

What we don’t know yet

I previously claimed the thrown assignment was in Git.run()’s collect() helper (a Stream.runFold reducer with in-place accumulator mutation). That is not confirmed:

  • I could not capture a stack trace pointing at that reducer.
  • A compiled-binary stress test that calls Git.run() directly did not reproduce the error.
  • A minimal, network-free AI SDK tool-call harness (MockLanguageModel emitting a tool call) did not reproduce either.

So at this point, the exact throw site is still unknown.

The best current explanation is still: a Bun minifier/codegen bug that only manifests with the full opencode module graph + the streamText tool-calling pipeline (similar class to known Bun minifier issues).

Potentially related upstream context

Vercel AI SDK (@ai-sdk/provider-utils) has a known readonly-environment compatibility issue in its JSON parsing helper (secureJsonParse toggles Error.stackTraceLimit). Our dependency tree includes a guarded set (try { Error.stackTraceLimit = 0 } …) but the restore write is unconditional. This could be relevant since tool-call argument parsing uses safeParseJSON()secureJsonParse(), but we do not have evidence yet that this is the actual throw site in opencode.

Proposed next step (to pin root cause)

Capture a stack trace from a failing compiled+minified binary with sourcemaps enabled, so we can identify the exact assignment that throws. Once we have the stack, we can decide whether the fix belongs in:

  • opencode (avoid a minifier-sensitive pattern),
  • the AI SDK (guard the restore write), or
  • Bun (minifier/codegen bug report with a minimized repro).

Mitigation PR

PR #25867 replaces the Stream.runFold accumulator mutation in Git.run()’s collect() with Stream.runForEach + local variables. This eliminated the crash in the original reproduction we used for this issue, but (per above) the exact mechanism is not yet proven.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions