{"record":{"id":"4af9439269eb5bb4","repo":"jestjs/jest","slug":"cannot-merge-config-in-form-of-callback","errorCode":null,"errorMessage":"Cannot merge config in form of callback","messagePattern":"Cannot merge config in form of callback","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/jest-config/src/index.ts","lineNumber":74,"sourceCode":"export function defineConfig(config: UserConfigFnObject): UserConfigFnObject;\nexport function defineConfig(config: UserConfigFnPromise): UserConfigFnPromise;\nexport function defineConfig(config: UserConfigFn): UserConfigFn;\nexport function defineConfig(config: UserConfigExport): UserConfigExport {\n  return config;\n}\n\n/**\n * Merges two configuration objects, where the second object takes precedence over the first one.\n */\nexport function mergeConfig<\n  D extends UserConfigExport,\n  O extends UserConfigExport,\n>(\n  defaults: D extends Function ? never : D,\n  overrides: O extends Function ? never : O,\n): JestTestConfigObject {\n  if (typeof defaults === 'function' || typeof overrides === 'function') {\n    throw new TypeError('Cannot merge config in form of callback');\n  }\n\n  return deepMerge.all([defaults, overrides]);\n}\n\nexport async function readConfig(\n  argv: Config.Argv,\n  packageRootOrConfig: string | Config.InitialOptions,\n  // Whether it needs to look into `--config` arg passed to CLI.\n  // It only used to read initial config. If the initial config contains\n  // `project` property, we don't want to read `--config` value and rather\n  // read individual configs for every project.\n  skipArgvConfigOption?: boolean,\n  parentConfigDirname?: string | null,\n  projectIndex = Number.POSITIVE_INFINITY,\n  skipMultipleConfigError = false,\n): Promise<ReadConfig> {\n  const {config: initialOptions, configPath} = await readInitialOptions(","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/jestjs/jest/blob/8e6d128e4a278059ecddecaa97400b04c8ae5fd9/packages/jest-config/src/index.ts#L56-L92","documentation":"mergeConfig (index.ts:66-78) deep-merges two plain config objects. It inspects their properties directly, so it cannot operate on the function/async-function config form that defineConfig supports. The runtime guard at index.ts:73-75 throws a TypeError if either argument is callable, matching the documented limitation that mergeConfig only accepts object configs.","triggerScenarios":"Calling mergeConfig(() => ({...}), {...}); mergeConfig({...}, async () => ({...})); passing a jest.config.ts that exports a function into mergeConfig; chaining defineConfig(fn) outputs into mergeConfig.","commonSituations":"Writing a base/override config split where one side is a function for env-based config; refactoring a config from object to callback form without updating the merge call; trying to merge presets defined as functions.","solutions":["Resolve the function to an object first: const base = await baseConfig(); then mergeConfig(base, overrides).","Restructure so both arguments to mergeConfig are plain objects (compute dynamic values before merging).","For env-dependent overrides, apply them inside a single callback config rather than merging two callbacks."],"exampleFix":"// before\nconst base = () => ({ testEnvironment: 'node' });\nmergeConfig(base, { verbose: true });\n// after\nconst base = { testEnvironment: 'node' };\nmergeConfig(base, { verbose: true });\n// or resolve first:\nconst base = await baseFn();\nmergeConfig(base, { verbose: true });","handlingStrategy":"type-guard","validationCode":"function safeMergeConfig<D extends object, O extends object>(d: D | (() => D), o: O | (() => O)) {\n  if (typeof d === 'function' || typeof o === 'function') {\n    throw new TypeError('Cannot mergeConfig function-form configs; resolve them to objects first');\n  }\n  return mergeConfig(d, o);\n}","typeGuard":"function isPlainConfigObject<T extends object>(c: unknown | (() => T) | (() => Promise<T>)): c is T {\n  return typeof c === 'object' && c !== null && typeof (c as any) !== 'function';\n}","tryCatchPattern":null,"preventionTips":["Resolve function/async configs to objects before calling mergeConfig.","Keep base/override configs as plain objects; put env-conditional logic elsewhere.","Type the mergeConfig inputs as objects (not the function union) to catch this at compile time."],"tags":["jest-config","mergeconfig","callback-config","type-error"],"backgroundTag":null,"analyzedSha":"8e6d128e4a278059ecddecaa97400b04c8ae5fd9","analyzedAt":"2026-08-10T18:11:27.960Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}