anomalyco / anomalyco/opencode

Bash tool / snapshot subsystem permanently loses ChildProcess.spawn capability after a transient trigger, no errno surfaced

Open
#43,876 1 comment 0 reactions 1 assignee View on GitHub

@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-tree pair 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

  1. 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.
  2. 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.
  3. If there's a known place where child_process.spawn/cross-spawn options capture
    long-lived state (an AbortController, 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.