rust-lang/rust-analyzer · warning · anyhow::Error

Invalid LSP resolve data

Error message

Invalid LSP resolve data

What it means

`handle_inlay_hints_resolve` stores an opaque resolve blob (range, hash, etc.) inside inlay hint `data`. Before re-resolving, it validates that the referenced file still exists in the snapshot via `snap.file_exists(file_id)`; if not, the stored data is considered corrupt or stale in a way that cannot be gracefully recovered, so it fails with `Invalid LSP resolve data` via `anyhow::ensure!`.

Source

Thrown at crates/rust-analyzer/src/handlers/request.rs:1859

pub(crate) fn handle_inlay_hints_resolve(
    snap: GlobalStateSnapshot,
    mut original_hint: InlayHint,
) -> anyhow::Result<InlayHint> {
    let _p = tracing::info_span!("handle_inlay_hints_resolve").entered();

    let Some(data) = original_hint.data.take() else {
        return Ok(original_hint);
    };
    let resolve_data: lsp_ext::InlayHintResolveData = serde_json::from_value(data)?;
    let file_id = FileId::from_raw(resolve_data.file_id);
    if resolve_data.version != snap.file_version(file_id) {
        tracing::warn!("Inlay hint resolve data is outdated");
        return Ok(original_hint);
    }
    let Some(hash) = resolve_data.hash.parse().ok() else {
        return Ok(original_hint);
    };
    anyhow::ensure!(snap.file_exists(file_id), "Invalid LSP resolve data");

    let line_index = snap.file_line_index(file_id)?;
    let range = from_proto::text_range(&line_index, resolve_data.resolve_range)?;

    let mut forced_resolve_inlay_hints_config = snap.config.inlay_hints(snap.minicore());
    forced_resolve_inlay_hints_config.fields_to_resolve = InlayFieldsToResolve::empty();
    let resolve_hints = snap.analysis.inlay_hints_resolve(
        &forced_resolve_inlay_hints_config,
        file_id,
        range,
        hash,
        |hint| {
            std::hash::BuildHasher::hash_one(
                &std::hash::BuildHasherDefault::<ide_db::FxHasher>::default(),
                hint,
            )
        },
    )?;

View on GitHub (pinned to e8f7e90aa3)

Solutions

  1. Have the client discard the stale hint and re-request `textDocument/inlayHint` for the current document.
  2. Reopen/reload the file in the editor so fresh hints (without stale data) are produced.
  3. If implementing a client, never cache inlay hint `data` beyond the server session.
  4. As a workaround, restart the language server to reset vfs state.

Example fix

// client-side before
resolveHint(oldCachedHint);

// after
const hints = await requestInlayHints(uri);
await resolveHint(hints.find(h => h.position === pos));
Defensive patterns

Strategy: try-catch

Validate before calling

// client-side: only resolve hints obtained in the same session for a still-open document
function canResolve(hint: InlayHint, openUris: Set<string>): boolean {
  const fid = (hint.data as any)?.file_id;
  return hint.data != null && fid != null && openUris.has(currentUri);
}

Type guard

function hasValidResolveData(hint: InlayHint): boolean {
  const d = hint.data as any;
  return !!d && typeof d === "object" && "resolve_range" in d && "hash" in d && "file_id" in d;
}

Try / catch

try {
  return await client.sendRequest("inlayHint/resolve", hint);
} catch (e) {
  // stale/invalid resolve data: drop the blob and refetch hints for the document
  log.warn("inlayHint/resolve failed, refetching", e);
  return (await client.sendRequest("textDocument/inlayHint", { textDocument: { uri }, range: fullRange }))[0] ?? hint;
}

Prevention

When it happens

Trigger: A client sends `inlayHint/resolve` with hint `data` whose `file_id`/`hash` blob points to a file that no longer exists in the server's vfs snapshot (file deleted, workspace changed, or a fabricated/tampered `data` payload).

Common situations: Stale editor state resolving hints after a file was closed/deleted; protocol fuzzing or third-party clients reusing cached hint data across sessions; version drift between a saved hint and the current workspace.

Related errors


AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03). Data as JSON: /api/errors/2317c474bdf01965. Report an issue: GitHub.