nodejs/node · error · RequestContentLengthMismatchError

UND_ERR_REQ_CONTENT_LENGTH_MISMATCH

UND_ERR_REQ_CONTENT_LENGTH_MISMATCH

Error message

Request body length does not match content-length header

What it means

Thrown by writeBlob() in client-h1.js (HTTP/1.1) as RequestContentLengthMismatchError (code UND_ERR_REQ_CONTENT_LENGTH_MISMATCH). When the request body is a Blob, undici compares the declared content-length to body.size before writing; if they differ, the wire bytes would contradict the header, so it refuses to send a malformed request.

Source

Thrown at deps/undici/src/lib/dispatcher/client-h1.js:1554

    abort(err)
  }
}

/**
 * @param {AbortCallback} abort
 * @param {Blob} body
 * @param {import('./client.js')} client
 * @param {import('../core/request.js')} request
 * @param {import('net').Socket} socket
 * @param {number} contentLength
 * @param {string} header
 * @param {boolean} expectsPayload
 * @returns {Promise<void>}
 */
async function writeBlob (abort, body, client, request, socket, contentLength, header, expectsPayload) {
  try {
    if (contentLength != null && contentLength !== body.size) {
      throw new RequestContentLengthMismatchError()
    }

    const buffer = Buffer.from(await body.arrayBuffer())

    socket.cork()
    socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1')
    socket.write(buffer)
    socket.uncork()

    request.onBodySent(buffer)
    request.onRequestSent()

    if (!expectsPayload && request.reset !== false) {
      socket[kReset] = true
    }

    client[kResume]()
  } catch (err) {

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Do NOT set content-length manually for Blob/Buffer bodies — let undici compute it from body.size.
  2. If you must set it, ensure the value equals body.size exactly (same byte length).
  3. Recompute the length from the exact buffer you are about to send.

Example fix

// before
await client.request({ method: 'POST', path: '/', body: blob, headers: { 'content-length': '100' } }) // != blob.size
// after — let undici derive content-length
await client.request({ method: 'POST', path: '/', body: blob })
Defensive patterns

Strategy: validation

Validate before calling

function blobRequest(client, path, blob, headers = {}) {
  delete headers['content-length'] // let undici derive from blob.size
  if (blob.size !== undefined && headers['content-length'] !== undefined) {
    if (Number(headers['content-length']) !== blob.size) throw new RangeError('content-length != blob.size')
  }
  return client.request({ method: 'POST', path, body: blob, headers })
}

Type guard

const lengthMatchesBlob = (headers, blob) => headers['content-length'] == null || Number(headers['content-length']) === blob.size

Try / catch

try { await client.request(req) } catch (e) { if (e.code === 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH') { delete req.headers['content-length']; /* retry */ } else throw e }

Prevention

When it happens

Trigger: request({ method: 'POST', body: new Blob([...]), headers: { 'content-length': 'N' } }) where N !== blob.size; passing a content-length header that you computed against a different (mutated) blob.

Common situations: Hard-coding or caching a content-length value while the Blob is rebuilt asynchronously; a proxy/middleware that rewrites content-length; mutating the Blob's underlying buffer after size was measured.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/2c69f700e783e7d0. Report an issue: GitHub.