sindresorhus/got · error · ReadError
ERR_HTTP_CONTENT_LENGTH_MISMATCH
ERR_HTTP_CONTENT_LENGTH_MISMATCH
Error message
Content-Length mismatch: expected ${this._expectedContentLength} bytes, received ${actualSize} bytes What it means
Produced at source/core/index.ts:900 by `_checkContentLengthMismatch`. When `strictContentLength` is true (the default) and the server sent a Content-Length header, got tracks the actual bytes received (`_compressedBytesCount` for compressed responses, `_downloadedSize` otherwise). If those numbers diverge, got emits a ReadError with code ERR_HTTP_CONTENT_LENGTH_MISMATCH. This mirrors Node's own validation: a mismatch means the response body was truncated or padded, so any parsed body is unreliable.
Source
Thrown at source/core/index.ts:900
(this._requestOptions as (NativeRequestOptions & {_alpnSocket?: Socket}) | undefined)?._alpnSocket?.destroy();
}
private _shouldIncrementallyDecodeBody(): boolean {
const {responseType, encoding} = this.options;
return Boolean(this._noPipe)
&& (responseType === 'text' || responseType === 'json')
&& isUtf8Encoding(encoding)
&& typeof globalThis.TextDecoder === 'function';
}
private _checkContentLengthMismatch(): boolean {
if (this.options.strictContentLength && this._expectedContentLength !== undefined) {
// Use compressed bytes count when available (for compressed responses),
// otherwise use _downloadedSize (for uncompressed responses)
const actualSize = this._compressedBytesCount ?? this._downloadedSize;
if (actualSize !== this._expectedContentLength) {
this._beforeError(new ReadError({
message: `Content-Length mismatch: expected ${this._expectedContentLength} bytes, received ${actualSize} bytes`,
name: 'Error',
code: 'ERR_HTTP_CONTENT_LENGTH_MISMATCH',
}, this));
return true;
}
}
return false;
}
private async _finalizeBody(): Promise<void> {
const {options} = this;
const headers = options.getInternalHeaders();
const isForm = !is.undefined(options.form);
// eslint-disable-next-line @typescript-eslint/naming-convention
const isJSON = !is.undefined(options.json);View on GitHub (pinned to e3924aa1e5)
Solutions
- Retry the request — the underlying cause is almost always a transient connection drop, and got's default retry will catch ECONNRESET but you may need to add ERR_HTTP_CONTENT_LENGTH_MISMATCH to retry.errorCodes.
- If you intentionally disable decompression (`decompress: false`), also set `strictContentLength: false` because the raw byte count will not match a Content-Length that describes the decompressed payload.
- Verify the upstream server/proxy is sending a correct Content-Length (or omitting it in favor of Transfer-Encoding: chunked) for compressed payloads.
Example fix
// before — strict content-length check on a compressed body you don't decompress
await got('https://api', { decompress: false });
// after — relax the check when intentionally reading raw bytes
await got('https://api', { decompress: false, strictContentLength: false }); Defensive patterns
Strategy: retry
Validate before calling
// Configure retry to cover the mismatch code, and relax strictContentLength when reading raw bytes.
const options = {
strictContentLength: !decompressDisabled, // set false when decompress: false
retry: { limit: 3, errorCodes: ['ERR_HTTP_CONTENT_LENGTH_MISMATCH', 'ECONNRESET'] }
}; Try / catch
import {HTTPError} from 'got';
try {
await got(url, { retry: { limit: 3 } });
} catch (error) {
if (error instanceof Error && (error as any).code === 'ERR_HTTP_CONTENT_LENGTH_MISMATCH') {
// transient truncation — got may have already retried; surface to caller for decision
throw new Error('Response body was truncated (Content-Length mismatch). Retry upstream.', { cause: error });
}
throw error;
} Prevention
- Include 'ERR_HTTP_CONTENT_LENGTH_MISMATCH' in retry.errorCodes for flaky upstreams.
- If you set decompress: false, also set strictContentLength: false — raw bytes won't match a decompressed Content-Length.
- Verify upstream servers/proxies send a correct Content-Length (or use chunked transfer-encoding) for compressed payloads.
When it happens
Trigger: Server closes the connection mid-body (truncated response); proxy or CDN miscounts bytes; compression layer (gzip/br/zstd) sends a Content-Length that doesn't match the compressed payload; server streams chunks and mis-declares the total length; client uses `decompress: false` so the raw byte count is compared against a Content-Length that was meant for the decompressed body.
Common situations: Flaky upstream that drops connections, reverse proxies that rewrite bodies without updating Content-Length, Brotli/zstd-compressed responses behind an HTTP/1 proxy, or disabling decompression while strictContentLength is on. Also seen when a server uses chunked transfer-encoding but also sets Content-Length.
Related errors
- ECONNRESET
- Using UNIX domain sockets but option `enableUnixSockets` is
- Invalid DNS lookup IP version: ${value as string}
- The maximum acceptable retry noise is +/- 100ms, got ${value
AI-assisted analysis of sindresorhus/got@e3924aa1e5 (2026-08-03).
Data as JSON: /data/errors/630fba689810138e.json.
Report an issue: GitHub.