denoland/deno · error · NodeError
ERR_HTTP_CONTENT_LENGTH_MISMATCH
ERR_HTTP_CONTENT_LENGTH_MISMATCH
Error message
Response body's content-length of ${this[kBytesWritten]} byte(s) does not match the content-length of ${this._contentLength} byte(s) set in header What it means
On end(), OutgoingMessage enforces strict content-length: when _checkStrictContentLength(msg) is true (msg.strictContentLength enabled AND a content-length is set AND the message has a body AND it is not chunked and content-length was not removed), it compares kBytesWritten (bytes actually written) with _contentLength (the declared header value). Any difference throws ERR_HTTP_CONTENT_LENGTH_MISMATCH instead of sending a lying header.
Source
Thrown at ext/node/polyfills/_http_outgoing.ts:614
return this;
} else if (!this._header) {
if (this.socket) {
this.socket.cork();
}
this._contentLength = 0;
this._implicitHeader();
}
if (typeof callback === "function") {
this.once("finish", callback);
}
if (
_checkStrictContentLength(this) &&
this[kBytesWritten] !== this._contentLength
) {
throw new ERR_HTTP_CONTENT_LENGTH_MISMATCH(
this[kBytesWritten],
this._contentLength,
);
}
const finish = FunctionPrototypeBind(onFinish, undefined, this);
if (this._hasBody && this.chunkedEncoding) {
this._send("0\r\n" + this._trailer + "\r\n", "latin1", finish);
} else if (!this._headerSent || this.writableLength || chunk) {
this._send("", "latin1", finish);
} else {
(globalThis as any).process.nextTick(finish);
}
if (this.socket) {
// Fully uncork connection on end().
this.socket._writableState.corked = 1;View on GitHub (pinned to 89f33cbef2)
Solutions
- Compute the length from the exact bytes sent: Buffer.byteLength(body, encoding)
- Apply all transformations (compression, templating) before measuring and setting content-length
- For unknown-size streams, remove the content-length header and use chunked transfer-encoding instead
Example fix
// before
res.setHeader('content-length', body.length); // 'héllo'.length = 5, bytes = 6
res.end(body);
// after
res.setHeader('content-length', Buffer.byteLength(body));
res.end(body); Defensive patterns
Strategy: validation
Validate before calling
const body = Buffer.from(payload, 'utf8');
res.setHeader('content-length', body.length);
res.end(body); // byte count always matches under strictContentLength Try / catch
try { res.end(body); } catch (e) { if (e.code === 'ERR_HTTP_CONTENT_LENGTH_MISMATCH') { /* recompute length from actual bytes and reissue response */ } else throw e; } Prevention
- Always measure with Buffer.byteLength / Buffer.byteLength(s, enc), never string.length
- Apply transforms (gzip, templating) before setting content-length
- For unknown sizes, delete content-length and let chunked encoding apply
When it happens
Trigger: setHeader('content-length', Buffer.byteLength(bodyA)) then end(bodyB) where the bodies differ; string vs byte miscounts (content-length computed on .length of a multibyte string); streams where the declared length does not match actual chunk sizes under strictContentLength servers.
Common situations: Manually setting content-length for keep-alive reuse but the body is transformed (gzip, template substitution) after counting; using str.length instead of Buffer.byteLength(str, encoding) for UTF-8; mutating the body between the length computation and end().
Related errors
- TypeError [ERR_INVALID_OPT_VALUE_ENCODING]: The value "${enc
- ERR_INVALID_ARG_TYPE
- ERR_INVALID_URL
- ERR_UNESCAPED_CHARACTERS
- ERR_INVALID_HTTP_TOKEN
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/e2f04bfaae9ed5b7.
Report an issue: GitHub.