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

  1. Send the standard LSP value: Content-Type: application/vscode-jsonrpc; charset=utf-8 (the starts_with check accepts the charset suffix)
  2. Or omit the Content-Type header entirely - the parser tolerates missing/unknown headers and only requires a valid Content-Length
  3. 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

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.