denoland/deno · error · Error

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

Thrown by OutgoingMessage.prototype.end() when strictContentLength is enabled and the number of body bytes actually written (this[kBytesWritten]) does not equal the content-length advertised in the header (this._contentLength). The check (_checkStrictContentLength) only applies when a content-length is set, the message has a body, is not chunked, and the content-length header was not removed. It exists to prevent sending responses whose declared length lies about the actual body size.

Solutions

  1. Compute the length with Buffer.byteLength(body, encoding) (or buf.byteLength) from the exact value you will write/end with, and set that as content-length.
  2. Drop the manual content-length header and let the runtime pick the length (end(body) on a fresh response) or use chunked transfer encoding.
  3. If the mismatch is intentional during migration/testing, set msg.strictContentLength = false to restore lenient Node default behavior.
  4. Audit middleware (compression, byte counting) that rewrites the body after the header was sized.

Example fix

// before
res.setHeader('content-length', 10); // guessed
res.write('héllo'); // 6 bytes, not 5
res.end();

// after
const body = 'héllo';
res.setHeader('content-length', Buffer.byteLength(body));
res.end(body);
Defensive patterns

Strategy: validation

Validate before calling

// before ending, confirm the byte totals agree when strictness is on
const written = Number(res.getHeader('content-length'));
if (res.strictContentLength && written !== null && bodyLength !== written) {
  res.removeHeader('content-length'); // fall back to chunked
}
res.end(body);

Try / catch

try {
  res.end(body);
} catch (err) {
  if (err.code === 'ERR_HTTP_CONTENT_LENGTH_MISMATCH') {
    // header already flushed: close connection so client sees a clean truncation
    res.socket?.destroy();
  } else throw err;
}

Prevention

When it happens

Trigger: res.strictContentLength = true (or the server sets it), then res.setHeader('content-length', N), write some bytes, and res.end() with a total != N. Example: setHeader('content-length', 10); res.write('hello'); res.end() -> 5 != 10.

Common situations: Manually setting content-length and then streaming a body whose size drifts (compression, encoding changes, transforms); computing length with .length instead of Buffer.byteLength for multi-byte strings; enabling strictContentLength (a Node >= 18 flag/property adopted by Deno's polyfill) on code that previously relied on lenient behavior; writing Buffer vs string and mixing up byte vs char counts.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/e2f04bfaae9ed5b7. Report an issue: GitHub.

Appendix: source

Thrown at ext/node/polyfills/_http_outgoing.ts:615

        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 9ad36f7a2c)