biomejs/biome · error · Error

could not find colon token in "${line}"

Error message

could not find colon token in "${line}"

What it means

While parsing a header block, every non-blank line must be a 'Name: Value' pair; a line with no colon character cannot be a header and throws (transport.ts:226-229). Note the blank-line check is an exact match against "\r\n" (transport.ts:210), so a peer that terminates the header block with a bare \n (LF only) produces the line "\n", which has no colon and hits this error. It also fires when the parser is desynchronized and is reading body or garbage bytes as header lines.

Source

Thrown at packages/@biomejs/backend-jsonrpc/src/transport.ts:228

		if (line === "\r\n") {
			const { contentLength, contentType } = readerState;
			if (typeof contentLength !== "number") {
				throw new Error(
					"incoming message from the remote workspace is missing the Content-Length header",
				);
			}

			this.readerState = {
				kind: ReaderStateKind.Body,
				contentLength,
				contentType,
			};
			return;
		}

		const colonIndex = line.indexOf(":");
		if (colonIndex < 0) {
			throw new Error(`could not find colon token in "${line}"`);
		}

		const headerName = line.substring(0, colonIndex);
		const headerValue = line.substring(colonIndex + 1).trim();

		switch (headerName) {
			case "Content-Length": {
				const value = Number.parseInt(headerValue, 10);
				readerState.contentLength = value;
				break;
			}
			case "Content-Type": {
				if (!headerValue.startsWith(MIME_JSONRPC)) {
					throw new Error(
						`invalid value for Content-Type expected "${MIME_JSONRPC}", got "${headerValue}"`,
					);
				}

View on GitHub (pinned to 7529811358)

Solutions

  1. Make the sender use CRLF (\r\n) line endings for every header line including the blank terminator, matching sendMessage (transport.ts:167).
  2. Check the preceding message's Content-Length: it must equal the exact byte length of the JSON body (use Buffer.byteLength / body.length of a Buffer, not string .length).
  3. Log raw chunks around the failure to find where framing desynchronized; the offending line is embedded in the error message.
  4. Confirm you are talking to a process that actually implements this framing (the Biome daemon), not a plain JSON stream.

Example fix

// before: LF-only header block (line "\n" has no colon -> throws)
socket.write(`Content-Length: ${body.length}\n\n`);
socket.write(body);

// after: CRLF header block
socket.write(`Content-Length: ${body.length}\r\nContent-Type: application/vscode-jsonrpc;charset=utf-8\r\n\r\n`);
socket.write(body);
Defensive patterns

Strategy: validation

Validate before calling

// Validate outgoing frames on the peer side before writing them
function frame(message) {
	const body = Buffer.from(JSON.stringify(message)); // byte length, not string length
	const headers = `Content-Length: ${body.length}\r\nContent-Type: application/vscode-jsonrpc;charset=utf-8\r\n\r\n`;
	if (!headers.endsWith("\r\n\r\n")) throw new Error("header block must end with CRLF CRLF");
	return Buffer.concat([Buffer.from(headers), body]);
}

Try / catch

// Header parsing runs in the 'data' event; treat any framing error as fatal for the connection:
process.on("uncaughtException", (err) => {
	if (err.message.includes("could not find colon token")) {
		// framing is desynchronized; recovery by re-reading is not possible
		transport.destroy();
		reconnect();
	} else {
		throw err;
	}
});

Prevention

When it happens

Trigger: The peer uses LF-only line endings in headers; a previous message declared a wrong Content-Length so the reader consumed too few/many bytes and now parses body JSON as headers; or any non-protocol bytes appear where a header line is expected.

Common situations: Custom test harnesses or mock servers writing headers with \n instead of \r\n; hand-rolled framing code that computes Content-Length from string length instead of byte length, desynchronizing the stream on multi-byte UTF-8 content.

Related errors


AI-assisted analysis of biomejs/biome@7529811358 (2026-08-16). Data as JSON: /api/errors/0718a5333bc0b6d9. Report an issue: GitHub.