denoland/deno · error · NodeRangeError

ERR_OUT_OF_RANGE

ERR_OUT_OF_RANGE

Error message

The value of "headersTimeout" is out of range. It must be <= requestTimeout. Received ${headersTimeout}

What it means

When the HTTP server is constructed, headersTimeout defaults to min(60000, requestTimeout); an explicit value is validated as a non-negative integer and then cross-checked: when both requestTimeout and headersTimeout are positive, headersTimeout must not exceed requestTimeout, otherwise ERR_OUT_OF_RANGE is thrown. The header-reading phase cannot be allowed to outlive the whole request deadline.

Source

Thrown at ext/node/polyfills/_http_server.js:1485

    validateInteger(requestTimeout, "requestTimeout", 0);
    this.requestTimeout = requestTimeout;
  } else {
    this.requestTimeout = 300_000; // 5 minutes
  }

  const headersTimeout = options.headersTimeout;
  if (headersTimeout !== undefined) {
    validateInteger(headersTimeout, "headersTimeout", 0);
    this.headersTimeout = headersTimeout;
  } else {
    this.headersTimeout = MathMin(60_000, this.requestTimeout);
  }

  if (
    this.requestTimeout > 0 && this.headersTimeout > 0 &&
    this.headersTimeout > this.requestTimeout
  ) {
    throw new ERR_OUT_OF_RANGE(
      "headersTimeout",
      "<= requestTimeout",
      headersTimeout,
    );
  }

  const keepAliveTimeout = options.keepAliveTimeout;
  if (keepAliveTimeout !== undefined) {
    validateInteger(keepAliveTimeout, "keepAliveTimeout", 0);
    this.keepAliveTimeout = keepAliveTimeout;
  } else {
    this.keepAliveTimeout = 5_000;
  }

  const connectionsCheckingInterval = options.connectionsCheckingInterval;
  if (connectionsCheckingInterval !== undefined) {
    validateInteger(
      connectionsCheckingInterval,

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Set headersTimeout <= requestTimeout, or omit it and accept the default min(60000, requestTimeout)
  2. If you need a larger headersTimeout, raise requestTimeout to at least that value
  3. Centralize timeout config and assert the invariant at startup
  4. Remember both are milliseconds and 0 disables the respective timeout

Example fix

// before
const server = http.createServer({ requestTimeout: 3_000, headersTimeout: 10_000 }, handler); // throws

// after
const server = http.createServer({ requestTimeout: 10_000, headersTimeout: 10_000 }, handler);
Defensive patterns

Strategy: validation

Validate before calling

function normalizeTimeouts(o) {
  const rt = o.requestTimeout ?? 300_000;
  const ht = o.headersTimeout ?? Math.min(60_000, rt);
  if (rt > 0 && ht > 0 && ht > rt) {
    o.headersTimeout = rt; // clamp: header phase cannot exceed the request deadline
  }
  return o;
}
const server = http.createServer(normalizeTimeouts(opts), handler);

Try / catch

try {
  server = http.createServer(opts, handler);
} catch (e) {
  if (e.code === 'ERR_OUT_OF_RANGE' && /headersTimeout/.test(e.message)) {
    const { headersTimeout, ...rest } = opts;
    server = http.createServer(rest, handler); // fall back to the default
  } else throw e;
}

Prevention

When it happens

Trigger: new http.Server({ requestTimeout: 3000, headersTimeout: 10000 }) or http.createServer with any options where 0 < requestTimeout < headersTimeout; the check runs in the constructor, so creation itself fails.

Common situations: Tuning server timeouts via config/env where the knobs are set independently; lowering requestTimeout for DoS protection while leaving a large headersTimeout; copying timeout numbers between Node versions whose defaults differed.

Understand the failure class

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/7f27b125a31623c6. Report an issue: GitHub.