Skip to content

fix(snapshot): replace synchronous diff with git subprocess in diffFull - #23366

Closed
sim590 wants to merge 1 commit into
anomalyco:devfrom
sim590:fix/snapshot-diff-hang
Closed

sim590 wants to merge 1 commit into
anomalyco:devfrom
sim590:fix/snapshot-diff-hang

Conversation

@sim590

@sim590 sim590 commented Apr 19, 2026 •

Copy link
Copy Markdown

Issue for this PR

Fixes #23362

Type of change

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

What does this PR do?

Snapshot.diffFull() calls formatPatch(structuredPatch(..., { context: Number.MAX_SAFE_INTEGER })) from the JS diff package synchronously on the main thread. On sessions with many file modifications, this blocks the event loop indefinitely — strace confirms all threads end up in FUTEX_WAIT with 0% CPU (async deadlock), freezing the TUI completely.

The trigger path is: SessionSummary.summarize() (fire-and-forget in prompt.ts) → computeDiff → snapshot.diffFull() → formatPatch(structuredPatch(...)) → hang.

The regression was introduced in b7fab49b6 (refactor(snapshot): store unified patches in file diffs #21244), identified via git bisect (9 steps between v1.3.3 and HEAD). Parent commit 463318486 is the last good commit.

This PR replaces the synchronous JS diff call with git diff --no-ext-diff --no-renames run as a subprocess. This produces equivalent unified diff output, runs non-blocking (does not starve the event loop), and is faster for large diffs. The diff npm package import is removed from this file as it is no longer needed.

Also addresses the main bottleneck (# 2 in the ranking) described in #22650, but only verified on TUI — web/desktop may have additional bottlenecks documented in that issue.

How did you verify your code works?

  • Built the binary and tested manually on Linux x86_64 against a session that reliably triggered the freeze (fork session with many file modifications, resend last message).
  • Without fix: TUI freezes immediately on resend, requires kill -9.
  • With fix: session resumes normally, no freeze.
  • Typecheck passes on all 13 packages.

Screenshots / recordings

N/A (not a UI change)

Checklist

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

formatPatch(structuredPatch(..., { context: Number.MAX_SAFE_INTEGER }))
blocks the event loop and freezes the TUI on sessions with many file
changes. Replace with git diff subprocess which is non-blocking and
faster for large diffs.
@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 Apr 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

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

@github-actions

Copy link
Copy Markdown
Contributor

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

Copy link
Copy Markdown
Contributor

Automated PR Cleanup

Thank you for contributing to opencode.

Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions.

This PR was closed because it matched the following cleanup criteria:

  • The PR was created more than 1 month ago
  • The PR had fewer than 2 positive reactions
  • Positive reactions are counted as thumbs-up, heart, celebration, or rocket reactions on the PR

PRs created within the last month are not affected by this cleanup.

If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate.

Thanks again for taking the time to contribute.

@sim590

sim590 commented May 19, 2026

Copy link
Copy Markdown
Author

This PR is still actively maintained. It was closed by the automated cleanup bot due to low reaction count, not due to any conformance issue.

The fix addresses a real TUI freeze caused by synchronous formatPatch(structuredPatch(..., { context: Number.MAX_SAFE_INTEGER })) in Snapshot.diffFull() — see #22650 and #23362 for full root cause analysis including git bisect results and strace evidence.

Could a maintainer please reopen this PR? Happy to rebase if needed.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TUI hangs indefinitely when resuming sessions with large file diffs (formatPatch/structuredPatch blocks event loop)

1 participant