nodejs/node · error · MaxOriginsReachedError

UND_ERR_MAX_ORIGINS_REACHED

UND_ERR_MAX_ORIGINS_REACHED

Error message

Maximum allowed origins reached

What it means

Thrown inside Agent's [kDispatch] as a MaxOriginsReachedError (code UND_ERR_MAX_ORIGINS_REACHED). The check is: this[kOrigins].size >= this[kOptions].maxOrigins AND the current origin is not already tracked. The Agent refuses to silently evict or grow beyond the configured cap, so a brand-new origin past the limit is rejected outright.

Solutions

  1. Raise maxOrigins to cover the expected origin cardinality (or omit it for Infinity).
  2. Pool repeated origins so they count once — make sure the origin string is normalized (trailing slash, lowercase host).
  3. Catch MaxOriginsReachedError and fall back to a fresh Client/Pool for overflow origins.

Example fix

// before
const agent = new Agent({ maxOrigins: 2 })
await agent.request({ origin: 'https://a.com', method: 'GET', path: '/' })
await agent.request({ origin: 'https://b.com', method: 'GET', path: '/' })
await agent.request({ origin: 'https://c.com', method: 'GET', path: '/' }) // throws
// after
const agent = new Agent({ maxOrigins: Infinity })
Defensive patterns

Strategy: fallback

Validate before calling

function boundedDispatch(agent, opts, handler, overflowPool) {
  try {
    return agent.dispatch(opts, handler)
  } catch (e) {
    if (e.code === 'UND_ERR_MAX_ORIGINS_REACHED') return overflowPool.dispatch(opts, handler)
    throw e
  }
}

Type guard

const isMaxOriginsError = (e) => e?.code === 'UND_ERR_MAX_ORIGINS_REACHED'

Try / catch

try {
  await agent.request({ origin, method, path })
} catch (e) {
  if (e.code === 'UND_ERR_MAX_ORIGINS_REACHED') {
    // raise maxOrigins or route via a fallback Client
  } else throw e
}

Prevention

When it happens

Trigger: new Agent({ maxOrigins: 3 }) then dispatching to four DISTINCT origins (the fourth, never-seen-before origin triggers the throw); a crawler hitting many hosts through a capped Agent.

Common situations: A polyglot client pointed at many microservices through one low-capped Agent; raising traffic to include more origins than the configured cap; mis-tuning maxOrigins down for memory and then seeing new hosts fail.

Related errors


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

Appendix: source

Thrown at deps/undici/src/lib/dispatcher/agent.js:86

    for (const dispatcher of this[kClients].values()) {
      ret += dispatcher[kRunning]
    }
    return ret
  }

  [kDispatch] (opts, handler) {
    let origin
    if (opts.origin && (typeof opts.origin === 'string' || opts.origin instanceof URL)) {
      origin = String(opts.origin)
    } else {
      throw new InvalidArgumentError('opts.origin must be a non-empty string or URL.')
    }

    const allowH2 = opts.allowH2 ?? this[kOptions].allowH2
    const key = allowH2 === false ? `${origin}#http1-only` : origin

    if (this[kOrigins].size >= this[kOptions].maxOrigins && !this[kOrigins].has(origin)) {
      throw new MaxOriginsReachedError()
    }

    let dispatcher = this[kClients].get(key)
    if (!dispatcher) {
      dispatcher = this[kFactory](opts.origin, allowH2 === false
        ? { ...this[kOptions], allowH2: false }
        : this[kOptions])

      const closeClientIfUnused = () => {
        if (this[kClients].get(key) !== dispatcher) {
          return
        }

        if (dispatcher[kConnected] > 0 || dispatcher[kBusy]) {
          return
        }

        this[kClients].delete(key)

View on GitHub (pinned to 1b2de5e052)