vitejs/vite · error · Error

Cannot merge config in form of callback

Error message

Cannot merge config in form of callback

What it means

Thrown by mergeConfig() when either the defaults or the overrides argument is a function. mergeConfig merges two plain config objects; the functional form of defineConfig/mergeConfig (which returns a function) is not accepted here and must be resolved to a plain object first.

Solutions

  1. Resolve the function to a plain object before merging: invoke the defineConfig callback (await if async) to get the config object.
  2. Use mergeConfig with plain objects only; do not pass the callback form as an argument.
  3. If you need the functional form, call mergeConfig(callback) with a single function argument at the top level instead of merging two values.

Example fix

// before
const base = defineConfig(async () => ({ plugins: [a] }))
mergeConfig(base, { plugins: [b] }) // throws (base is a function)
// after
const baseObj = await base()
mergeConfig(baseObj, { plugins: [b] })
Defensive patterns

Strategy: type-guard

Validate before calling

function isPlainConfig(v: unknown): v is Record<string, any> {
  return v != null && typeof v !== 'function'
}
if (!isPlainConfig(defaults) || !isPlainConfig(overrides)) {
  throw new TypeError('mergeConfig needs plain objects, not functions')
}

Type guard

function isPlainConfigObject(v: unknown): v is Record<string, any> {
  return v != null && typeof v === 'object' && typeof v !== 'function'
}

Prevention

When it happens

Trigger: Calling mergeConfig(fn, overrides) or mergeConfig(defaults, fn) where fn is a function — e.g. the result of defineConfig(async () => ({...})) or a mergeConfig callback. The check `typeof ... === 'function'` is at utils.ts:1574.

Common situations: Programmatically merging a base config that was authored with the callback form of defineConfig. Passing an un-invoked mergeConfig callback (mergeConfig also supports mergeConfig(callback) at the top level, but two-argument mergeConfig does not).

Related errors


AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11). Data as JSON: /api/errors/ccfbbd300b9a0876. Report an issue: GitHub.

Appendix: source

Thrown at packages/vite/src/node/utils.ts:1575

      )
      continue
    }

    merged[key] = value
  }
  return merged
}

export function mergeConfig<
  D extends Record<string, any>,
  O extends Record<string, any>,
>(
  defaults: D extends Function ? never : D,
  overrides: O extends Function ? never : O,
  isRoot = true,
): Record<string, any> {
  if (typeof defaults === 'function' || typeof overrides === 'function') {
    throw new Error(`Cannot merge config in form of callback`)
  }

  return mergeConfigRecursively(defaults, overrides, isRoot ? '' : '.')
}

function mergeInput(a?: InputOption, b?: InputOption): InputOption | undefined {
  if (!a) return b
  if (!b) return a

  if (typeof a === 'string' && typeof b === 'string') {
    return [a, b]
  }
  if (Array.isArray(a) && (typeof b === 'string' || Array.isArray(b))) {
    return [...a, ...(Array.isArray(b) ? b : [b])]
  }
  if (Array.isArray(b) && (typeof a === 'string' || Array.isArray(a))) {
    return [...(Array.isArray(a) ? a : [a]), ...b]
  }

View on GitHub (pinned to b4d66fee14)