nodejs/node · error · TypeError

expected opts.methods to be an array, got ${typeof methods}

Error message

expected opts.methods to be an array, got ${typeof methods}

What it means

Thrown by the deduplicate interceptor's factory function when the `methods` option is destructured from `opts` but is not an Array. The deduplicate interceptor merges concurrent identical safe-method requests into a single network call, so it must know which HTTP methods are eligible. Because the factory destructures `methods` with a default of `['GET']`, this fires only when you explicitly pass a non-array value. It is a synchronous TypeError raised at interceptor construction time (when you call `createDeduplicateInterceptor(opts)` or compose it), not per-request.

Source

Thrown at deps/undici/src/lib/interceptor/deduplicate.js:27

/**
 * @param {import('../../types/interceptors.d.ts').default.DeduplicateInterceptorOpts} [opts]
 * @returns {import('../../types/dispatcher.d.ts').default.DispatcherComposeInterceptor}
 */
module.exports = (opts = {}) => {
  const {
    methods = ['GET'],
    skipHeaderNames = [],
    excludeHeaderNames = [],
    maxBufferSize = 5 * 1024 * 1024
  } = opts

  if (typeof opts !== 'object' || opts === null) {
    throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? 'null' : typeof opts}`)
  }

  if (!Array.isArray(methods)) {
    throw new TypeError(`expected opts.methods to be an array, got ${typeof methods}`)
  }

  for (const method of methods) {
    if (!util.safeHTTPMethods.includes(method)) {
      throw new TypeError(`expected opts.methods to only contain safe HTTP methods, got ${method}`)
    }
  }

  if (!Array.isArray(skipHeaderNames)) {
    throw new TypeError(`expected opts.skipHeaderNames to be an array, got ${typeof skipHeaderNames}`)
  }

  if (!Array.isArray(excludeHeaderNames)) {
    throw new TypeError(`expected opts.excludeHeaderNames to be an array, got ${typeof excludeHeaderNames}`)
  }

  if (!Number.isFinite(maxBufferSize) || maxBufferSize <= 0) {
    throw new TypeError(`expected opts.maxBufferSize to be a positive finite number, got ${maxBufferSize}`)

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Change the `methods` option to an array of HTTP method strings, e.g. `methods: ['GET']` or `methods: ['GET', 'HEAD']`.
  2. If loading options from external config, coerce with `Array.isArray(opts.methods) ? opts.methods : [opts.methods]` before passing them in.
  3. If you meant to deduplicate only one method, pass a one-element array rather than a bare string.
  4. Audit the surrounding config object for other shape mismatches (skipHeaderNames, excludeHeaderNames, maxBufferSize) since they validate in the same block.

Example fix

// before
const agent = new Agent().compose([deduplicate({ methods: 'GET' })])

// after
const agent = new Agent().compose([deduplicate({ methods: ['GET'] })])
Defensive patterns

Strategy: validation

Validate before calling

function validateDeduplicateOpts(opts) {
  if (!Array.isArray(opts.methods)) {
    opts.methods = Array.isArray(opts.methods) ? opts.methods : [opts.methods].filter(Boolean)
  }
  if (!Array.isArray(opts.methods)) {
    throw new TypeError('opts.methods must be an array of safe HTTP methods')
  }
  return opts
}

Type guard

function isMethodArray(v) {
  return Array.isArray(v) && v.every(m => typeof m === 'string')
}

Prevention

When it happens

Trigger: Calling the deduplicate interceptor factory with `opts.methods` set to a string (e.g. `'GET'`), a number, a plain object, `true`, or any other non-array. Passing `methods: 'GET'` instead of `methods: ['GET']` is the canonical trigger. The check `Array.isArray(methods)` fails before any method-content validation runs.

Common situations: Copying a single method from a config file as a bare string; migrating from a single-method API to the array form; reading `methods` out of JSON where it was serialized as a scalar; TypeScript users bypassing types with `as any`. The default `['GET']` masks the requirement, so developers first encounter it only when they try to add `HEAD`.

Related errors


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