Skip to content

fix: replace all mutable Stream fold/collect patterns with immutable runForEach, revert effect to beta.57#25867

Open
stephanschielke wants to merge 11 commits intoanomalyco:devfrom
stephanschielke:fix/git-runfold-readonly-mutation
Open

fix: replace all mutable Stream fold/collect patterns with immutable runForEach, revert effect to beta.57#25867
stephanschielke wants to merge 11 commits intoanomalyco:devfrom
stephanschielke:fix/git-runfold-readonly-mutation

Conversation

@stephanschielke
Copy link
Copy Markdown

@stephanschielke stephanschielke commented May 5, 2026

Issue for this PR

Closes #25873
Related: #25835

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Replaces all mutable Stream.runCollect, Stream.runFold, and Stream.mkUint8Array call sites with immutable Stream.runForEach + local variable accumulators. Also reverts effect from 4.0.0-beta.59 to 4.0.0-beta.57.

The crash is caused by two factors combined (neither alone triggers it):

  1. minify: true in the build script (PR build(opencode): shrink single-file executable size #22362) causes Bun's JSC to freeze objects passed through fold callbacks in compiled binaries.
  2. effect@4.0.0-beta.58 (Effect-TS/effect-smol#2098) changed Stream.mkUint8Array from an immutable fold (new object per iteration) to a mutable accumulator (acc.push(); return acc). Stream.runCollect and Channel.runCollect already had the same mutable pattern.

v1.14.33 (minify + beta.57) worked because beta.57 creates new objects each iteration. v1.14.34+ (minify + beta.59) crashes because the fold returns the same mutated object, which JSC freezes between iterations.

Effect maintainer @mikearnaldi confirms: "This is 100% a bug in Bun's minification implementation."

Changes:

  • snapshot/index.ts: replaced Stream.mkUint8Array with collectUint8 helper using runForEach + local vars
  • git/index.ts: replaced mutable Stream.runFold with runForEach + local vars
  • file/ripgrep.ts (2 sites): replaced Stream.runCollect with runForEach + local array
  • file/index.ts: replaced Stream.runCollect with runForEach + local array
  • tool/skill.ts: replaced Stream.runCollect with runForEach + local array
  • tool/glob.ts: replaced Stream.runCollect with runForEach + local array
  • cli/cmd/debug/ripgrep.ts: replaced Stream.runCollect with runForEach + local array
  • package.json + bun.lock: reverted effect to 4.0.0-beta.57

Related PRs (alternative fixes):

Upstream: Effect-TS/effect-smol#2126, Effect-TS/effect-smol#2127

Known Bun issues: oven-sh/bun#13394, oven-sh/bun#12655

How did you verify your code works?

  1. Traced root cause via Effect repo diff (beta.57..beta.59), confirmed Stream.mkUint8Array is the only relevant change
  2. opencode.db queries: all 4 original errors have fully parsed tool input, ruling out AI SDK JSON parsing
  3. Reproduction: local-anthropic agent on broken binary, first call succeeded, second call (task tool, not git) failed with Attempting to define property on object that is not extensible
  4. Typecheck passes (only pre-existing TS2416 in bus/global.ts, same on dev)
  5. Zero remaining Stream.runCollect, Stream.runFold, or Stream.mkUint8Array calls in opencode src (confirmed via grep + ast-grep)
  6. Does NOT reproduce in bun run, bun build --compile without --minify, or with effect@4.0.0-beta.57

Screenshots / recordings

N/A (not a UI change)

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

The collect() function in Git.run() mutates the fold accumulator in-place
(acc.bytes += ..., acc.truncated = ..., acc.chunks.push(...)). Since
effect@4.0.0-beta.59 (bumped in v1.14.34), Stream.runFold may treat
accumulators as readonly, causing 'Attempted to assign to readonly property'
on every git subprocess invocation.

Replace with Stream.runForEach + local mutable state which is idiomatic
for side-effectful stream consumption and avoids accumulator immutability
assumptions entirely.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions github-actions Bot added needs:compliance This means the issue will auto-close after 2 hours. and removed needs:compliance This means the issue will auto-close after 2 hours. needs:issue labels May 5, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

Thanks for updating your PR! It now meets our contributing guidelines. 👍

…utable fold accumulator crash in Bun compiled binaries
stephanschielke and others added 2 commits May 6, 2026 09:55
PR anomalyco#25524 bumped effect from beta.57 to beta.59 as a routine chore with no feature dependency. Beta.58 (Effect-TS/effect-smol#2098) introduced a mutable Channel.runFold accumulator in Stream.mkUint8Array that crashes in Bun --compile --minify binaries. Reverting to last known-good version.
@stephanschielke stephanschielke changed the title fix(git): replace mutating Stream.runFold with Stream.runForEach fix: mutable Stream.runFold crash in compiled binaries, revert effect to beta.57 May 6, 2026
stephanschielke and others added 3 commits May 6, 2026 15:51
…patterns

Stream.runCollect uses Channel.runFold with acc.push(o); return acc, which causes JSC to freeze the accumulator in bun --compile --minify binaries. Replace all 6 call sites with Stream.runForEach + local array accumulator. Files changed: file/ripgrep.ts (2 sites), file/index.ts (1), tool/skill.ts (1), tool/glob.ts (1), cli/cmd/debug/ripgrep.ts (1). Related: anomalyco#25873, Effect-TS/effect-smol#2126
@stephanschielke stephanschielke changed the title fix: mutable Stream.runFold crash in compiled binaries, revert effect to beta.57 fix: replace all mutable Stream fold/collect patterns with immutable runForEach, revert effect to beta.57 May 6, 2026
@github-actions github-actions Bot added needs:compliance This means the issue will auto-close after 2 hours. and removed needs:compliance This means the issue will auto-close after 2 hours. labels May 6, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

Thanks for updating your PR! It now meets our contributing guidelines. 👍

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

1 participant