copy/v86 · warning
The request contains an invalid header: "%s"
Error message
The request contains an invalid header: "%s"
What it means
The fake HTTP server (fetch_network) parses each request header line with net.parse_http_header; a line that doesn't split into a valid key/value pair logs a console warning and the server responds with 400 Bad Request, closing the connection. This is a server-side response behavior, not an exception — the message is the warning text, where %s is the offending raw header line.
Source
Thrown at src/browser/fetch_network.js:173
target = new URL(first_line[1]);
}
else
{
target = new URL("http://host" + first_line[1]);
}
if(typeof window !== "undefined" && target.protocol === "http:" && window.location.protocol === "https:")
{
// fix "Mixed Content" errors
target.protocol = "https:";
}
const req_headers = new Headers();
for(let i = 1; i < header_lines.length; ++i)
{
const header = this.net.parse_http_header(header_lines[i]);
if(!header)
{
console.warn('The request contains an invalid header: "%s"', header_lines[i]);
this.net.respond_text_and_close(this, 400, "Bad Request", `Invalid header in request: ${header_lines[i]}`);
return;
}
if(header.key.toLowerCase() === "host") target.host = header.value;
else req_headers.append(header.key, header.value);
}
if(!this.net.cors_proxy && /^\d+\.external$/.test(target.hostname))
{
dbg_log("Request to localhost: " + target.href, LOG_FETCH);
const localport = parseInt(target.hostname.split(".")[0], 10);
if(!isNaN(localport) && localport > 0 && localport < 65536)
{
target.protocol = "http:";
target.hostname = "localhost";
target.port = localport.toString(10);
}
elseView on GitHub (pinned to 180830d539)
Solutions
- Fix the client inside the VM to send well-formed HTTP/1.1 headers (each header must be 'Key: Value')
- Check that the guest isn't sending HTTPS/TLS traffic to the plain-HTTP proxy port
- Update the guest's HTTP client software / proxy configuration to standards-compliant output
- If a specific header is intentionally nonstandard, extend parse_http_header handling or bypass the fetch backend for that traffic
Example fix
// before (guest request)
fetch("http://host/").setHeader("BadHeader NoColon", "");
// after
fetch("http://host/", { headers: { "Accept": "*/*" } }); // valid 'Key: Value' headers Defensive patterns
Strategy: validation
Validate before calling
function isWellFormedHeaderLine(line) {
const idx = line.indexOf(":");
return idx > 0 && /^[-!#$%&'*+.^_`|~0-9A-Za-z]+$/.test(line.slice(0, idx).trim()) &&
!/[\r\n]/.test(line);
}
// sanitize guest request headers before they reach the fake server
if (!headers.every(isWellFormedHeaderLine)) fixOrRejectRequest(); Type guard
function isValidHttpHeader(line) {
const i = line.indexOf(":");
return i > 0 && line.slice(0, i).trim().length > 0 && !/[\r\n]/.test(line);
} Try / catch
// Not a thrown exception: intercept via the server's response handling
if (response.status === 400 && /Invalid header in request:/.test(await response.text())) {
logMalformedGuestRequest();
retryWithSanitizedHeaders();
} Prevention
- Ensure the guest's HTTP client emits standards-compliant 'Key: Value' headers
- Never point plain-HTTP proxy settings at a TLS port (or vice versa)
- Update old/buggy guest HTTP clients
- Monitor console for this warning to spot misconfigured guest software early
When it happens
Trigger: The guest OS sends an HTTP request containing a malformed header line (no colon, invalid characters, or a badly formed continuation) to a fetch-based network-backed server; on_data_http iterates header_lines[i] for i>=1 and any parse failure triggers the 400 path.
Common situations: Guest software producing non-conformant HTTP (custom tools, old clients, binary junk sent to port 80); a URL fetcher inside the VM hitting the proxy with garbage (e.g. plain TLS bytes sent to an HTTP port); misconfigured guest proxy settings pointing at the wrong port.
Related errors
AI-assisted analysis of copy/v86@180830d539 (2026-08-31).
Data as JSON: /api/errors/7f8a4d30acd1b775.
Report an issue: GitHub.