Skip to content

Sessions become unusable due to large LSP diagnostics (Lua + possibly others) #6310

Closed as not planned

Description

@maurits150

Description

After using the edit/write tools a few times in larger LSP enabled Lua (.lua extension) projects, sessions slow to a crawl.

Root Cause

  • Edit/write tools store full LSP diagnostics in metadata.
  • Lua LSP returns diagnostics for entire workspace (for me thousands of files, tens of thousands of diagnostics
  • This bloats session storage rapidly, as full diagnostics are attached to EACH message that does an edit/write tool call.
  • Other LSPs may have the same issue.

Impact

  • OpenCode session grows to 1GB+ quickly
  • New messages takes minutes to send: OpenCode sits at 100% CPU usage (presumably decoding JSON).
  • Cancelling via ESC becomes unresponsive.

Workaround

Potential fix
In packages/opencode/src/tool/edit.ts and write.ts, change from storing the entire diagnostics object to just the edited file's diagnostics:

+++ b/packages/opencode/src/tool/edit.ts   (or write.ts) 
     return {
       metadata: {
-        diagnostics,
+        // Only store diagnostics for the edited file, not entire workspace
+        diagnostics: { [normalizedFilepath]: diagnostics[normalizedFilepath] ?? [] },

Additional context (which Opus 4.5 found)
Commit aedb555 ("fix: limit LSP diagnostics to prevent context window waste") also addressed a related problem of sending too many diagnostics to the LLM, by limiting the output message to max 20 diagnostics per file and max 5 project files.

However, that commit only limited what goes in the tool's output string shown to the LLM. It didn't touch the storage layer - the full workspace diagnostics (all files, all issues) were still being saved to session metadata on every edit/write. Your proposed fix compliments that work by also limiting what gets persisted to disk.

OpenCode version

1.0.204 (latest as of writing)

Steps to reproduce

  1. Extract the test project ZIP (contains 1000 test lua files + an AGENTS.md to tell the agent to continue the pattern)
  2. Start opencode in that folder and send a message.
  3. Watch how a 44.3MB json file gets created under opencode/storage/part/, containing diagnostics of all 1000 files, even tho the agent only touched 2 files.

Screenshot and/or share link

Image

Operating System

Linux Mint 21.3

Terminal

Guake

Activity

  1. added
    perfIndicates a performance issue or need for optimization
    on Dec 28, 2025
  2. ry2009 commented on Jan 2, 2026

    @ry2009
    Contributor

    done a couple things with lsp budget and diagnostic here is targeted one: #6671

  3. mblarsen commented on Feb 27, 2026

    @mblarsen

    Also happens for python (pyright)

    opencode version 1.2.15

  4. maurits150 commented on Feb 27, 2026

    @maurits150
    Author

    Yup this is still a problem - tested again using test project ZIP

    18MB additional disk used for 1 message

    Image

    Forgot to do opencode -v there but it's 1.2.15.

  5. mengdehong commented on Mar 4, 2026

    @mengdehong

    The same problem exists in Rust

  6. removed
    bugSomething isn't working
    perfIndicates a performance issue or need for optimization
    on May 3, 2026
  7. Mart-Bogdan commented on Jun 4, 2026

    @Mart-Bogdan

    Strange. for C# it ouputs diagnostics only for currently edited file

  8. full-bars commented on Jun 24, 2026

    @full-bars

    Confirming this is still present in opencode 1.17.9 (current as of writing), well after PR #6671 was closed without merging back in March.

    New data point: also reproduces with Go (gopls), not just Lua/Python/Rust. In my case it was worse than just slowness — it crashed the process entirely. A ~66K-line generated Go file (a data table, not hand-written code) triggered gopls's simplifycompositelit hint once per line (~65,871 diagnostics). Because that file existed in 3 separate LSP workspace roots in my config, the same diagnostics array got duplicated 3x per snapshot. Each edit/write tool-call part ballooned to ~67MB regardless of how small the actual edit was. Over a long session (7,576 tool-call parts) that's 2.05GB of part data for one session.

    Beyond the slowness described above, once a session crosses this size, opencode -c hard-crashes with SIGABRT trying to resume it — and opencode export fails too (see #22072, same root cause: uncapped diagnostics growth, just surfacing as a different symptom).

    The fix proposed in #6671 (scope diagnostics to the touched file) looks right, but might also need to dedupe identical diagnostics across multiple LSP roots for the same logical file, since that's what pushed my case from "annoying" to "crashes the app."

    Workaround I'm trying in the meantime: disable the specific noisy analyzer via opencode config (e.g. for gopls, "analyses": {"simplifycompositelit": false} in lsp.gopls.initialization). Note this is untested for long-term effectiveness — I haven't yet confirmed it actually prevents bloat from recurring over a fresh long session, and it's per-analyzer/per-LSP, not a general fix.

  9. github-actions commented on Aug 24, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

  10. maurits150 commented on Aug 24, 2026

    @maurits150
    Author

    ??

  11. Mart-Bogdan commented on Aug 24, 2026

    @Mart-Bogdan

    Yes, it's wild that they've set up auto close on issues.

  12. one-pyy commented on Oct 5, 2026

    @one-pyy

    Hit exactly this and, since the issue only auto-closed for inactivity (people still confirm it on newer versions), I put together a workaround plugin while waiting for an upstream fix.

    opencode-edit-diagnostics-pruner — https://github.com/one-pyy/opencode-edit-diagnostics-pruner

    • A tool.execute.after hook that rewrites the tool result so state.metadata.diagnostics keeps only the files edited by that call (apply_patch, edit, write). Tool output, title, input, and provider metadata are preserved, and the diagnostics text returned to the model is unchanged — so neither the UI replay nor the model feedback changes, only the persisted map shrinks.
    • A separate CLI (history.mjs) that prunes the same diagnostics from an existing session database, for sessions that already ballooned. It takes a full SQLite online backup first, validates it, and applies every change in a single transaction (with an explicit --no-backup opt-out).

    On my database the history cleanup removed ~540 MB of diagnostics JSON (327 parts + 327 event copies). For the affected session, send time went from ~59s to ~6s and sampled peak memory from ~9.75 GiB to ~2.54 GiB — single measurement, not a promise. The gain scales with session length and with how many plugins pass that metadata around. It does not address the event table growth in #33356, only the diagnostics payload.

    Not affiliated with the project; sharing in case it helps anyone until upstream trims the persisted diagnostics.

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