anomalyco / anomalyco/opencode
Bash tool / snapshot subsystem permanently loses ChildProcess.spawn capability after a transient trigger, no errno surfaced
@rekram1-node is already working on this.
Since Aug 21, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Summary
Two independent OpenCode/Bun processes, on unrelated projects, permanently lost the
ability to spawn any git subprocess for the snapshot subsystem within ~2 minutes of
each other, after hours of prior successful operation. Neither recovered without a
process restart. The user-facing Bash tool in the affected session also became
unusable for the rest of that session (echo ok itself failed), per the session's
own contemporaneous notes.
No OS errno is ever surfaced — the error is wrapped as a bare
Unknown: ChildProcess.spawn (<command>), which is itself part of the problem: with
the real errno swallowed, this is unfixable and undiagnosable from the app's own logs.
Evidence (from OpenCode's own ~/.local/share/opencode/log/opencode.log)
Four sessions were alive in the hour before the incident (run=374b6f08,
run=67126b47, run=6ea0185d, run=9cc3defa). Only two broke:
run=9cc3defa (project A) — created 2026-08-17T16:51:51Z, successfully tracked
snapshots (real git hashes) for 4h11m. At 2026-08-17T21:03:14.546Z its
snapshot git-spawn failed for the first time and never recovered: 333 consecutive
failures logged, zero successes, for the rest of the session's life.
timestamp=2026-08-17T21:03:14.546Z level=WARN run=9cc3defa message="failed to list snapshot files" diffCode=1 diffStderr="Command failed: git -c core.autocrlf=false -c core.longpaths=true -c core.symlinks=true -c core.quotepath=false --git-dir /Users/.../opencode/snapshot/<hash>/<hash> --work-tree /Users/.../<project-A> diff-files --name-only -z -- .: Unknown: ChildProcess.spawn (git -c core.autocrlf=false ... diff-files --name-only -z -- .)" otherCode=1 otherStderr="Command failed: git ... ls-files --full-name --others --exclude-standard -z -- .: Unknown: ChildProcess.spawn (...)"
run=67126b47 — a completely unrelated project (project B, different
projectID, different directory) — started failing the identical way at
2026-08-17T21:01:30.333Z, 104 seconds earlier.
The other two concurrently-alive sessions (374b6f08, 6ea0185d) never logged a
spawn failure in this window.
Why this rules out a few obvious explanations
- Not a stale/moved path: the exact
--git-dir/--work-treepair from a
similarly-affected session (a different incident, same signature, investigated the
same day) works instantly when run by hand in an interactive shell. The path,
command, and args are all fine in isolation. - Not a hard per-user process/fd ceiling: only 2 of 4 concurrently-alive sessions
broke. A hard ceiling being crossed would be expected to affect all processes
sharing that ceiling, not a subset. - Not proportional to spawn call volume: the process issuing by far the most
subprocess spawns in the same window (an interactive orchestrator session doing
active investigation work) never failed once.
Working theory
A brief, shared, external trigger (candidates: a transient fd/process-table pressure
spike, a file-system-event storm from Spotlight/Time Machine/cloud sync driving a
spawn burst in every file-watching process at once, or a security/EDR client briefly
gating posix_spawn) hit whichever processes happened to be actively spawning at that
exact moment. The trigger itself is transient and clears within seconds — but it
appears to leave the spawn subsystem of the affected process permanently corrupted
for the remainder of that process's life. This would match cross-spawn throwing
synchronously on a spawn failure and wedging whatever internal state
(packages/core/src/tool/bash.ts / packages/core/src/cross-spawn-spawner.ts) tracks
in-flight shell/spawn machinery — see #41301, which already acknowledges a
synchronous-throw-wedges-the-shell-abstraction failure mode in this exact area.
Ask
- Surface the real underlying error/errno instead of wrapping it as
Unknown: ChildProcess.spawn (...)— this is why the incident went undiagnosed
for 4 days; any future occurrence deserves a real error code. - If a spawn throws synchronously (per #41301), recover the internal spawn/shell
state for that session rather than leaving it permanently wedged — right now the
only recovery is a full process restart. - If there's a known place where
child_process.spawn/cross-spawnoptions capture
long-lived state (anAbortController, worker-thread handle, or similar) once per
session, consider whether a single failure there is expected to be fatal for every
future call, and if not, why it currently behaves that way.
Happy to provide the full raw log excerpt (multiple hundred lines, redacted paths
available on request) if useful.
Environment
- OpenCode version: 1.18.15
- Platform: macOS Sonoma 23.6.0, aarch64
- Provider: amazon-bedrock (Claude models)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.