anomalyco / anomalyco/opencode

core: session never drains when Snapshot.capture() stalls on huge untracked tree — git add hangs, execution claim never released

Open
#48,657 0 comments 0 reactions 1 assignee View on GitHub

@neriousy is already working on this.

Since Sep 12, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Description

Summary

Sending a prompt in a project with a very large untracked (and not gitignored)
file tree leaves the session stuck forever with no response. SessionStep.attempt
runs Snapshot.capture() before llm.stream(), and the capture's
git add --all --pathspec-from-file=- burns 100% CPU in pathspec matching for
10+ minutes (167k untracked files). No model call is ever made, and the
time_suspended execution claim is never released, so the session never drains.

Expected Behavior

The step either completes the snapshot in reasonable time, skips/times out a
pathological capture and still calls the model, or surfaces a snapshot error —
and the execution claim is released so the session stays usable.

Actual Behavior

  • The runner claims the session (session_v2.time_suspended set 64ms after
    creation) and blocks in Snapshot.capture():
    packages/core/src/session/runner/step.ts:72 runs before llm.stream()
    at step.ts:102, so the provider is never contacted.
  • Git.index.refresh (packages/core/src/git.ts:381) enumerates all untracked
    files via ls-files --others and feeds ~167k paths to a single
    git add --all --sparse --pathspec-from-file=- --pathspec-file-nul
    in the snapshot repo (~/.local/share/opencode/snapshot/<project>/<hash>/).
  • That git add (child of the server process) ran 11+ minutes at ~99% CPU;
    sample shows 100% of time in read_directory_recursive
    treat_pathmatch_pathspec_with_flagsstrncmp — i.e. pathspec
    matching cost, not I/O. It also holds index.lock in the snapshot repo.
  • time_suspended is never cleared (time_updated frozen), no
    Failed to drain Session error is logged, the UI just shows nothing.
    Side symptoms: a transient GET /api/session/<id> 404 (request raced
    session-row insert by ~74ms) and SSE reconnect churn, both harmless.

Additional Context

  • Frequency: deterministic given the tree shape; every step start re-captures,
    so restarting the server re-triggers it (startup recovery resumes the
    claimed session).
  • Workaround: kill the stuck git add, add the directory to the project's
    .gitignore, then restart the server / resend.
  • Related (same feature area, different mechanisms, not duplicates):
    #46138 (Snapshot.diffFull serializes full patch text into message rows),
    #47854 (EventV2 duplicates large snapshot payloads),
    #47022 (~72GB DB growth),
    #47605 (sessions stuck busy via model-response timeout),
    #47988 (cancelled task blocks resume/amend).
  • Possible fix directions (suggestion only): cap/skip capture when the
    untracked candidate set exceeds a threshold (log + continue with
    snapshot: undefined, which capture() already supports); add a timeout to
    Git.tree.capture; avoid feeding hundreds of thousands of explicit
    pathspecs to one git add (e.g. rely on directory-level adds or
    status --porcelain cone/sparse scoping).
Plugins

nothing globally; project-local .opencode/plugins/use-vp.ts present

OpenCode version

local (dev install, bun run src/index.ts serve) checkout of v2.0.2

Steps to reproduce
  1. Have a git project with a huge untracked, not-ignored directory
    (in my case shadcn_ui_components_2026/: 167,696 files, 685MB;
    167,697 untracked vs 502 tracked; the project .gitignore did not cover it).
  2. Open the web UI, create/select a session in that project, send any prompt.
  3. Observe: user message is persisted (session_message has the user part),
    but no assistant message ever appears and no model request is logged.
Screenshot and/or share link

No response

Operating System

Darwin 24.6.0 arm64

Terminal

web UI in browser (TERM_PROGRAM not set in shell env). Shell: /bin/zsh

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.