biomejs/biome · error · anyhow::Error
Failed to parse URI {}: {e}
Error message
Failed to parse URI {}: {e} What it means
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.
Source
Thrown at crates/biome_lsp/src/handlers/analysis.rs:401
pub url: String,
pub rule: Option<RuleSelector>,
pub kind: CodeActionResolveKind,
pub range: TextRange,
pub project_key: ProjectKey,
}
fn resolve_code_action_data(data: Option<Value>) -> Result<(CodeActionResolveData, Uri)> {
let data = data
.as_ref()
.context("Missing code action data. This is usually caused by the client not supporting codeAction/resolve.")?;
let resolve_data: CodeActionResolveData = serde_json::from_value(data.clone())
.context("Failed to deserialize code action resolve data. This is an internal error, please report it.")?;
let url: Uri = resolve_data
.url
.parse()
.map_err(|e| anyhow::anyhow!("Failed to parse URI {}: {e}", resolve_data.url))?;
Ok((resolve_data, url))
}
/// Resolve a code action by computing the actual text edit.
///
/// Called when the user selects a code action from the lightbulb menu.
/// The action's `data` field contains a [`CodeActionResolveData`] token that
/// identifies which rule and action category to compute.
pub(crate) fn code_action_resolve(
session: &Session,
params: lsp::CodeAction,
) -> Result<lsp::CodeAction, LspError> {
let (resolve_data, url) = resolve_code_action_data(params.data.clone())?;
let path = session.file_path(&url)?;
let Some(doc) = session.document(&url) else {
return Err(extension_error(&path).into());View on GitHub (pinned to 7529811358)
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.
Example fix
// before: client rebuilds the action before resolving (url can be corrupted or dropped)
await connection.sendRequest("codeAction/resolve", {
title: action.title,
kind: action.kind,
data: { url: currentFileUri }, // reconstructed, not the original blob
});
// after: client echoes the exact action the server produced
await connection.sendRequest("codeAction/resolve", action); Defensive patterns
Strategy: validation
Validate before calling
// Client-side: only resolve actions whose data blob is the server's own opaque token
function isResolvableAction(action) {
return (
action !== null &&
typeof action === "object" &&
typeof action.title === "string" &&
typeof action.data === "object" &&
action.data !== null &&
typeof action.data.url === "string" &&
action.data.url.length > 0
);
}
if (isResolvableAction(action)) {
const resolved = await connection.sendRequest("codeAction/resolve", action);
} Type guard
type ServerActionData = { url: string; rule?: unknown; kind: string; range: unknown; project_key: number };
function hasServerActionData(action: unknown): action is { title: string; data: ServerActionData } {
const a = action as { data?: unknown } | null;
return (
!!a &&
typeof a === "object" &&
!!a.data &&
typeof (a.data as { url?: unknown }).url === "string" &&
(a.data as { url: string }).url.length > 0
);
} Try / catch
try {
const resolved = await connection.sendRequest("codeAction/resolve", action);
} catch (err) {
if (String(err?.message ?? err).includes("Failed to parse URI")) {
// The action's data is stale or corrupted; re-request code actions for the document instead of retrying.
const fresh = await connection.sendRequest("textDocument/codeAction", currentParams);
return fresh;
}
throw err;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to convert URL to URI: {err}
- invalid range: start offset ({start:?}) > end offset ({end:?
- incoming message from the remote workspace is missing the Co
- could not find colon token in "${line}"
- invalid value for Content-Type expected "${MIME_JSONRPC}", g
AI-assisted analysis of biomejs/biome@7529811358 (2026-08-16).
Data as JSON: /api/errors/bad8314b37da3835.
Report an issue: GitHub.