{"record":{"id":"bad8314b37da3835","repo":"biomejs/biome","slug":"failed-to-parse-uri-e","errorCode":null,"errorMessage":"Failed to parse URI {}: {e}","messagePattern":"Failed to parse URI (.+?): (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/biome_lsp/src/handlers/analysis.rs","lineNumber":401,"sourceCode":"    pub url: String,\n    pub rule: Option<RuleSelector>,\n    pub kind: CodeActionResolveKind,\n    pub range: TextRange,\n    pub project_key: ProjectKey,\n}\n\nfn resolve_code_action_data(data: Option<Value>) -> Result<(CodeActionResolveData, Uri)> {\n    let data = data\n        .as_ref()\n        .context(\"Missing code action data. This is usually caused by the client not supporting codeAction/resolve.\")?;\n\n    let resolve_data: CodeActionResolveData = serde_json::from_value(data.clone())\n        .context(\"Failed to deserialize code action resolve data. This is an internal error, please report it.\")?;\n\n    let url: Uri = resolve_data\n        .url\n        .parse()\n        .map_err(|e| anyhow::anyhow!(\"Failed to parse URI {}: {e}\", resolve_data.url))?;\n\n    Ok((resolve_data, url))\n}\n\n/// Resolve a code action by computing the actual text edit.\n///\n/// Called when the user selects a code action from the lightbulb menu.\n/// The action's `data` field contains a [`CodeActionResolveData`] token that\n/// identifies which rule and action category to compute.\npub(crate) fn code_action_resolve(\n    session: &Session,\n    params: lsp::CodeAction,\n) -> Result<lsp::CodeAction, LspError> {\n    let (resolve_data, url) = resolve_code_action_data(params.data.clone())?;\n\n    let path = session.file_path(&url)?;\n    let Some(doc) = session.document(&url) else {\n        return Err(extension_error(&path).into());","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/biomejs/biome/blob/7529811358079edb5a2a9d4a5f67a9f639a63f3a/crates/biome_lsp/src/handlers/analysis.rs#L383-L419","documentation":"During codeAction/resolve, the Biome LSP server reads back the opaque data blob it originally attached to a code action (CodeActionResolveData with a url field, analysis.rs:381-388) and parses the stored url string into an LSP Uri (analysis.rs:398-401). Because that url is generated by the server itself as the document URI, a parse failure means the blob was corrupted or replaced somewhere in its round trip through the editor client.","triggerScenarios":"An LSP client that re-serializes, trims, or rebuilds codeAction.data before echoing it in codeAction/resolve; a client resolving a stale code action captured before a workspace/root change, whose url no longer parses; a custom client wrapper constructing the resolve request by hand instead of forwarding the original action object.","commonSituations":"Custom editor integrations or scripts that call codeAction/resolve directly; stale lightbulb actions after renaming a project or switching workspace folders; a client middleware that normalizes or drops unknown fields inside data.","solutions":["Reload the file or restart the editor session so fresh code actions carry server-generated data for the current URIs.","If you implement an LSP client, forward the codeAction object from textDocument/codeAction back to codeAction/resolve byte-for-byte, including data.","Disable any middleware that re-serializes or filters fields inside codeAction.data.","If data round-trips untouched and the error persists, report it to the Biome repository with the URI shown in the message."],"exampleFix":"// before: client rebuilds the action before resolving (url can be corrupted or dropped)\nawait connection.sendRequest(\"codeAction/resolve\", {\n\ttitle: action.title,\n\tkind: action.kind,\n\tdata: { url: currentFileUri }, // reconstructed, not the original blob\n});\n\n// after: client echoes the exact action the server produced\nawait connection.sendRequest(\"codeAction/resolve\", action);","handlingStrategy":"validation","validationCode":"// Client-side: only resolve actions whose data blob is the server's own opaque token\nfunction isResolvableAction(action) {\n\treturn (\n\t\taction !== null &&\n\t\ttypeof action === \"object\" &&\n\t\ttypeof action.title === \"string\" &&\n\t\ttypeof action.data === \"object\" &&\n\t\taction.data !== null &&\n\t\ttypeof action.data.url === \"string\" &&\n\t\taction.data.url.length > 0\n\t);\n}\n\nif (isResolvableAction(action)) {\n\tconst resolved = await connection.sendRequest(\"codeAction/resolve\", action);\n}","typeGuard":"type ServerActionData = { url: string; rule?: unknown; kind: string; range: unknown; project_key: number };\n\nfunction hasServerActionData(action: unknown): action is { title: string; data: ServerActionData } {\n\tconst a = action as { data?: unknown } | null;\n\treturn (\n\t\t!!a &&\n\t\ttypeof a === \"object\" &&\n\t\t!!a.data &&\n\t\ttypeof (a.data as { url?: unknown }).url === \"string\" &&\n\t\t(a.data as { url: string }).url.length > 0\n\t);\n}","tryCatchPattern":"try {\n\tconst resolved = await connection.sendRequest(\"codeAction/resolve\", action);\n} catch (err) {\n\tif (String(err?.message ?? err).includes(\"Failed to parse URI\")) {\n\t\t// The action's data is stale or corrupted; re-request code actions for the document instead of retrying.\n\t\tconst fresh = await connection.sendRequest(\"textDocument/codeAction\", currentParams);\n\t\treturn fresh;\n\t}\n\tthrow err;\n}","preventionTips":["Forward the codeAction object received from textDocument/codeAction back to codeAction/resolve unchanged, including data.","Never rebuild the data blob on the client; treat it as an opaque token.","Re-request code actions after workspace/root changes so stale URIs inside data cannot be resolved.","Disable client middleware that normalizes, filters, or re-serializes unknown fields."],"tags":["lsp","code-action","uri","editor-integration","protocol"],"backgroundTag":"lsp-codeaction-data-invalid","analyzedSha":"7529811358079edb5a2a9d4a5f67a9f639a63f3a","analyzedAt":"2026-08-16T22:13:27.842Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}