Skip to content

service: 100% CPU hang when snapshotting a very large git worktree #50734

Closed

Description

@jonaspm

Summary

On Linux/WSL, the v2 background service hangs at ~100% CPU and stops answering HTTP when a session runs in a directory that OpenCode treats as a git project containing an extremely large number of files. The snapshot pass enumerates the entire tree on the JS thread (git ls-files --others --exclude-standard output: ~57 MB / ~1.4M paths), blocking the event loop. opencode service status then reports stopped even though the process is alive and the port is still listening.

This also creates a restart loop: if the service is killed mid-turn, the session row is left with time_suspended set; the next opencode service start auto-resumes it, repeats the same snapshot walk, and hangs again.

Environment

  • opencode version: 2.0.14 (channel=latest local=false)
  • OS: WSL2 Ubuntu 24.04, kernel 6.18.33.2-microsoft-standard-WSL2, WSL 2.7.14.0, Windows 10.0.26200
  • Terminal: Windows Terminal (TERM=xterm-256color)
  • Shell: /bin/bash
  • Install/channel: latest, managed binary at ~/.opencode/bin/opencode
  • Active plugins: local plugin ./plugins/caveman/plugin.js; remote MCP server faces. Both were removed for a control run (clean XDG_CONFIG_HOME) and the hang still reproduced.

Reproduction

  1. In a home directory with ~1.4M files, create an empty git repo: git init ~ (0 commits, no remote, no .gitignore).
  2. opencode service start — starts fine and prints its URL.
  3. Open a session in ~, or restart the service after a home-dir session was interrupted mid-turn so it is auto-resumed at startup.
  4. The service spawns:
    git --git-dir ~/.local/share/opencode/snapshot/global/<hash> --work-tree ~ ls-files --others --exclude-standard -z -- .
    and then blocks.

Expected Behavior

  • The service stays responsive while snapshotting.
  • Very large directory walks are capped, skipped, or performed off the main thread.
  • A stalled session resume backs off instead of pinning the server.
  • service status distinguishes "busy/hung" from "stopped".

Actual Behavior

  • Process alive, port listening (ss shows Recv-Q 9–14 on the listener), /api/info times out, ~100% CPU for minutes.
  • opencode service status prints stopped.
  • Log output stops right after the snapshot ls-files entry; nothing further is written.
  • After a mid-turn kill, session_v2 has a row with non-null time_suspended and an incremented resume_attempts; every restart immediately hangs again.

Additional Context

Control tests:

  • Fresh empty DB with the same config → service healthy.
  • Copy of the affected DB (VACUUM INTO copy) → healthy after clearing time_suspended on the affected session; hangs again as soon as a home-dir session is resumed.
  • Suspended session in a normal repo (~158k files) → resumes fine, stays responsive.

Measurements:

  • Home directory: 1,458,088 files.
  • git ls-files --others --exclude-standard -z output: 56,875,543 bytes; manual walk takes ~3 s, and JS-side processing of the result blocks far longer.
  • Self-referential snapshot: the snapshot store lives inside the worktree (~/.local/share/opencode/snapshot/...), and its own walk lists 1,476 files from the store.
  • DB was 1.24 GB with 246,133 free pages out of 303,277; VACUUM shrank it to 229 MB. Not the root cause, but it also slowed startup.

Log excerpt (service boot, then silence after the snapshot command):

timestamp=... run=2f1c16c4 message="spawning process" command=git args="[\"rev-parse\",\"--git-dir\",\"--git-common-dir\",\"--show-toplevel\"]" cwd=~ role=server
timestamp=... run=2f1c16c4 message="spawning process" command=git args="[\"--git-dir\",\"~/.local/share/opencode/snapshot/global/a9dfd4ad...\",\"--work-tree\",\"~\",\"diff-files\",\"--name-only\",\"-z\",\"--\",\".\"]" cwd=~ role=server
timestamp=... run=2f1c16c4 message="spawning process" command=git args="[\"--git-dir\",\"~/.local/share/opencode/snapshot/global/a9dfd4ad...\",\"--work-tree\",\"~\",\"ls-files\",\"--others\",\"--exclude-standard\",\"-z\",\"--\",\".\"]" cwd=~ role=server
timestamp=... run=2f1c16c4 message="mcp connected" server=faces tools=25 role=server
-- no further entries until the next manual `service status` invocation --

Additional observations:

  • Two stale project rows with worktree / repeatedly log worktree discovery failed directory=/ strategy=git error=Worktree.DirectoryUnavailableError.
  • Workaround that stopped the hang: renaming the junk empty ~/.git (no commits, no remote) removed the home-dir snapshot walk; the service has stayed healthy since (CPU ~3%).

Activity

  1. github-actions commented on Sep 22, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    Your workaround (renaming ~/.git to remove the home-dir as a git project) matches the one found by others in #32981. You may want to add your detailed measurements and restart-loop findings as a comment on #32981 since they add valuable new context about the issue.

  2. jonaspm commented on Sep 22, 2026

    @jonaspm
    Author

    Cross-posted the V2 measurements and the restart-loop findings to the canonical thread: #32981 (comment)

    Leaving this issue open for now since the V2 background-service failure mode (service unresponsive + service status reporting stopped + auto-resume restart loop) differs from the V1 TUI freeze. Say the word if you would rather have it closed as a duplicate.

  3. neriousy commented on Oct 20, 2026

    @neriousy
    Member

    Thanks for the detailed report. Version 2.0.26 removes quadratic snapshot path processing that could lock up the service on very large worktrees.

    Update with opencode upgrade or npm i -g @opencode/cli@latest (desktop: update the app).

    Please comment or reopen if the service still hangs with your worktree on that version or newer.

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions