biomejs/biome · error · anyhow::Error
invalid value for Content-Type expected \"application/vscode
Error message
invalid value for Content-Type expected \"application/vscode-jsonrpc\", got {value:?} What it means
Header validation while reading LSP messages over the CLI service transport (crates/biome_cli/src/service/mod.rs:476). Each header line is split at the first colon; when the name is exactly 'Content-Type', the value must start with 'application/vscode-jsonrpc' (a charset suffix such as '; charset=utf-8' is accepted via starts_with). Any other value fails the ensure! and aborts the connection with this message. A missing Content-Type header is fine - only Content-Length is mandatory in LSP framing.
Source
Thrown at crates/biome_cli/src/service/mod.rs:475
fn from_str(line: &str) -> Result<Self, Self::Err> {
let colon = line
.find(':')
.with_context(|| format!("could not find colon token in {line:?}"))?;
let (name, value) = line.split_at(colon);
let value = value[1..].trim();
match name {
"Content-Length" => {
let value = value.parse().with_context(|| {
format!("could not parse Content-Length header value {value:?}")
})?;
Ok(Self::ContentLength(value))
}
"Content-Type" => {
ensure!(
value.starts_with("application/vscode-jsonrpc"),
"invalid value for Content-Type expected \"application/vscode-jsonrpc\", got {value:?}"
);
Ok(Self::ContentType)
}
_ => Ok(Self::Unknown(name.into())),
}
}
}
View on GitHub (pinned to 45a19bbf17)
Solutions
- Send the standard LSP value: Content-Type: application/vscode-jsonrpc; charset=utf-8 (the starts_with check accepts the charset suffix)
- Or omit the Content-Type header entirely - the parser tolerates missing/unknown headers and only requires a valid Content-Length
- If a proxy rewrites the header, bypass it for the Biome connection or configure it to preserve the original value
Example fix
# before (raw frame sent to the Biome server socket)
Content-Type: application/json
{...}
# after
Content-Type: application/vscode-jsonrpc; charset=utf-8
{...} Defensive patterns
Strategy: validation
Validate before calling
// TypeScript - build LSP frames with the accepted Content-Type (or none at all)
function writeMessage(socket: net.Socket, body: string): void {
const headers =
`Content-Length: ${Buffer.byteLength(body)}\r\n` +
`Content-Type: application/vscode-jsonrpc; charset=utf-8\r\n\r\n`;
socket.write(headers + body);
} Type guard
const isVscodeJsonrpcContentType = (value: string): boolean =>
value.trim().startsWith('application/vscode-jsonrpc'); Prevention
- Reuse an established LSP client library (vscode-jsonrpc, lspower) instead of hand-rolling framing
- If you must hand-roll, remember only Content-Length is mandatory - send no Content-Type rather than a wrong one
- Validate header values against the LSP spec in your client's tests before talking to Biome
When it happens
Trigger: Speaking the LSP wire protocol to a Biome server (e.g. biome __run-server or the daemon socket) and sending a header line 'Content-Type: <value>' where value does not start with application/vscode-jsonrpc - for example 'application/json' or 'text/plain'. Triggered by custom clients, hand-written socket scripts, or proxies that rewrite the header.
Common situations: Custom editor integrations and test harnesses that reuse a generic JSON-RPC framing implementation with Content-Type: application/json; HTTP proxies or middleware injecting a default Content-Type; curl-based experiments against the socket using the wrong header.
Related errors
AI-assisted analysis of biomejs/biome@45a19bbf17 (2026-08-20).
Data as JSON: /api/errors/4686973fdc5ea76f.
Report an issue: GitHub.