rust-lang/rust-analyzer · error

we never provide code actions for excluded files

Error message

we never provide code actions for excluded files

What it means

handle_code_action_resolve resolves the FileId recorded in the code action's data. Since rust-analyzer never produces code actions for excluded files, failing to map the URI to a FileId breaks the invariant and panics via expect. It guards the code-action resolve-data contract between server and client.

Source

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

        if intersect_fix_range {
            res.push(fix.action.clone());
        }
    }

    Ok(Some(res))
}

pub(crate) fn handle_code_action_resolve(
    snap: GlobalStateSnapshot,
    mut code_action: lsp_ext::CodeAction,
) -> anyhow::Result<lsp_ext::CodeAction> {
    let _p = tracing::info_span!("handle_code_action_resolve").entered();
    let Some(params) = code_action.data.take() else {
        return Ok(code_action);
    };

    let file_id = from_proto::file_id(&snap, &params.code_action_params.text_document.uri)?
        .expect("we never provide code actions for excluded files");
    if snap.file_version(file_id) != params.version {
        return Err(invalid_params_error("stale code action".to_owned()).into());
    }
    let line_index = snap.file_line_index(file_id)?;
    let range = from_proto::text_range(&line_index, params.code_action_params.range)?;
    let frange = FileRange { file_id, range };
    let source_root = snap.analysis.source_root_id(file_id)?;

    let mut assists_config = snap.config.assist(Some(source_root));
    assists_config.allowed = params
        .code_action_params
        .context
        .only
        .map(|it| it.into_iter().filter_map(from_proto::assist_kind).collect());

    let (assist_index, assist_resolve) = match parse_action_id(&params.id) {
        Ok(parsed_data) => parsed_data,
        Err(e) => {

View on GitHub (pinned to e8f7e90aa3)

Solutions

  1. Re-run the code action request on the currently open file so fresh data with a valid FileId is produced.
  2. Check that the target file is not excluded by settings like files.exclude or rust-analyzer's workspace discovery config.
  3. Reopen/re-add the file to the workspace (didOpen) before resolving old code actions.
  4. Update rust-analyzer and the client extension; discard cached code actions from before a reload.
Defensive patterns

Strategy: validation

Validate before calling

// client: verify the action's embedded document is still open and not excluded before resolving
const uri = action.data?.codeActionParams?.textDocument?.uri;
if (!uri || isExcluded(uri) || !workspace.textDocuments.some(d => d.uri.toString() === uri)) {
  return action; // cannot resolve safely
}

Type guard

function isResolvableCodeAction(a: unknown): a is { data: { codeActionParams: { textDocument: { uri: string }; range: unknown }; version: number } } {
  return typeof a === 'object' && a !== null && 'data' in a &&
    typeof (a as any)?.data?.codeActionParams?.textDocument?.uri === 'string';
}

Try / catch

try {
  return await client.sendRequest('codeAction/resolve', action);
} catch (e) {
  console.warn('code action resolve failed; returning unmodified action', e);
  return action;
}

Prevention

When it happens

Trigger: A client resolves a code action whose embedded textDocument.uri no longer maps to a tracked file — the file was closed, excluded from the workspace, is an untitled/virtual document, or the URI scheme is not convertible by from_proto::file_id.

Common situations: Keeping code actions around after closing or excluding a file, editors that persist quick-fixes across workspace reloads, files filtered out by client-side glob exclusions, multi-root workspaces where the file moved to an unregistered root.

Related errors


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