一键导入
debug-lsp
Debug LSP server issues including hangs, incorrect responses, performance problems, or crashes. Use when troubleshooting the language server.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Debug LSP server issues including hangs, incorrect responses, performance problems, or crashes. Use when troubleshooting the language server.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Add new GraphQL lint rules following project patterns. Use when implementing a lint rule, adding validation logic, or extending the linter with new checks.
Create pull requests following project standards. Use when opening a PR, preparing changes for review, or running gh pr create.
Add new IDE/LSP features like hover, goto definition, find references, or completion. Use when implementing editor features, LSP handlers, or IDE functionality.
Audit test organization and patterns. Use PROACTIVELY after writing new tests to self-review, or when reviewing test changes in PRs. Checks unit vs integration test placement, TestDatabase patterns, and caching verification.
Fix bugs using the two-commit structure with failing test first. Use when fixing bugs, addressing issues, or correcting incorrect behavior.
Review pull requests against project standards. Use when reviewing PRs, checking code quality, or providing feedback on changes.
| name | debug-lsp |
| description | Debug LSP server issues including hangs, incorrect responses, performance problems, or crashes. Use when troubleshooting the language server. |
| user-invocable | true |
| argument-hint | [symptom description] |
| allowed-tools | Bash(cargo build *), Bash(cargo test *), Bash(cargo run *), Bash(RUST_LOG=*), Read, Grep, Glob |
Follow this guide when debugging LSP issues.
ls -la target/debug/graphql-lsp
If missing, rebuild:
cargo build
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | target/debug/graphql-lsp
Should return a valid JSON-RPC response.
RUST_LOG=debug target/debug/graphql-lsp
# LSP layer only
RUST_LOG=graphql_lsp=debug target/debug/graphql-lsp
# Analysis layer
RUST_LOG=graphql_analysis=debug target/debug/graphql-lsp
# Multiple modules
RUST_LOG=graphql_lsp=debug,graphql_analysis=info,graphql_hir=trace target/debug/graphql-lsp
| Level | Use For |
|---|---|
| ERROR | Critical failures only |
| WARN | Non-fatal issues |
| INFO | High-level operations |
| DEBUG | Detailed operations, timing |
| TRACE | Deep debugging |
For performance issues, use distributed tracing:
cargo build --features otel
docker run -d --name jaeger \
-p 4317:4317 \
-p 16686:16686 \
jaegertracing/all-in-one:latest
OTEL_TRACES_ENABLED=1 target/debug/graphql-lsp
Open http://localhost:16686 in your browser.
Look for:
Symptoms: Editor shows no diagnostics, features don't work
Debug steps:
Symptoms: tracing::error! from the global panic hook, then an InternalError JSON-RPC response (id intact). Individual requests fail but the server stays up.
What to look for:
std::panic::catch_unwind(AssertUnwindSafe(...)) (see GlobalState::spawn_with_snapshot). On a caught panic the worker sends back a Response::new_err(id, ErrorCode::InternalError, "internal error: handler panicked"), so the request id always gets a response and in_flight is cleared.install_panic_hook in crates/lsp/src/lib.rs) emits tracing::error! with the message, source location, and a backtrace if RUST_BACKTRACE=1 is set. Set the env var on the LSP server process to get backtraces.LineIndex after rapid edits. LineIndex::line_col clamps and warns rather than panicking, but if you see LineIndex::line_col offset is past end of source or landed mid-character warnings, that's a pre-existing bug somewhere in the diagnostics pipeline that needs investigation.Symptoms: LSP stops responding, CPU stays low.
Background: After the sync-LSP migration, GlobalState/AnalysisHost mutations only happen on the main thread, and snapshots live on workers. The whole pre-migration deadlock class (snapshot blocked on a side-channel RwLock while the main thread held the writer) is gone. A hang today is much more likely to be:
select! arm — e.g. a notification handler is running a long Salsa query inline instead of using spawn_diagnostics_for_uri / spawn_with_snapshot. Workers idle while the main thread blocks; the recv(connection.receiver) arm never fires.threadpool::execute closure. Don't.recv(state.introspection_result_receiver) not firing).Debug steps:
RUST_LOG=debug. Look at which select! arm last fired in the main loop.spawn_diagnostics_for_uri / spawn_diagnostics_batch.state.in_flight — the request is either still in flight on a worker, or its response was dropped because the id was no longer in in_flight (cancelled).The structural rule (see crates/CLAUDE.md "Snapshot Safety"): Analysis snapshots and AnalysisHost must not share any non-Salsa lock. If you need snapshot-visible data, put it in a Salsa input. If you find yourself adding an Arc<RwLock<...>> to AnalysisHost whose contents a snapshot would also read, stop and reach for a #[salsa::input] instead.
The lifecycle rule still applies on the main thread when a notification handler holds a snapshot and then writes:
// WRONG
let snapshot = host.snapshot();
let result = snapshot.some_query();
host.add_file(...); // Hangs: snapshot still alive on this thread
// RIGHT — let update_file_and_snapshot do the write+snapshot atomically:
let (_is_new, snapshot) = host.update_file_and_snapshot(&file_path, &content, lang, kind);
// snapshot is now safe to send to a worker
Symptoms: Wrong errors, missing errors, stale errors
Debug steps:
all_fragments() querySymptoms: Laggy editor, delayed diagnostics
Debug steps:
cargo benchExpected performance:
Symptoms: Extension not activating, wrong files targeted
Debug steps:
documentSelector includes target languagescd editors/vscode && npm run compile