{"id":"d9e701684f345306","repo":"vitejs/vite","slug":"config-must-export-or-return-an-object","errorCode":null,"errorMessage":"config must export or return an object.","messagePattern":"config must export or return an object\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vite/src/node/config.ts","lineNumber":2428,"sourceCode":"\n  try {\n    const { configExport, dependencies } = await (configLoader === 'bundle'\n      ? bundleAndLoadConfigFile(\n          resolvedPath,\n          configRoot,\n          logLevel,\n          customLogger,\n        )\n      : configLoader === 'runner'\n        ? runnerImportConfigFile(resolvedPath)\n        : nativeImportConfigFile(resolvedPath))\n    debug?.(`config file loaded in ${getTime()}`)\n\n    const config = await (typeof configExport === 'function'\n      ? configExport(configEnv)\n      : configExport)\n    if (!isObject(config)) {\n      throw new Error(`config must export or return an object.`)\n    }\n\n    return {\n      path: normalizePath(resolvedPath),\n      config,\n      dependencies,\n    }\n  } catch (e) {\n    const logger = createLogger(logLevel, { customLogger })\n    checkBadCharactersInPath('The config path', 'file', resolvedPath, logger)\n    logger.error(colors.red(`failed to load config from ${resolvedPath}`), {\n      error: e,\n    })\n    throw e\n  }\n}\n\nasync function nativeImportConfigFile(","sourceCodeStart":2410,"sourceCodeEnd":2446,"githubUrl":"https://github.com/vitejs/vite/blob/89620f09afcfef6b35e7bb8660132ab5b4d0cd3b/packages/vite/src/node/config.ts#L2410-L2446","documentation":"In loadConfigFromFile (config.ts:2424-2428), after evaluating the config export (calling it if it's a function), Vite checks isObject(config). If the config file exports/returns a non-object (e.g. a string, number, array, or undefined), it throws because a Vite config must be a plain object.","triggerScenarios":"A vite.config file whose default export or returned value is not an object — e.g. `export default 'vite'`, `export default 42`, a function that returns an array, or a file that exports nothing (undefined).","commonSituations":"Default export forgotten/typo'd; config file written as a list of plugins without wrapping in an object; a function config that returns the wrong shape; partial migration leaving an incomplete file.","solutions":["Ensure the config file exports a plain object: export default { ... } (or defineConfig(() => ({ ... }))).","If using a function form, make sure it returns an object, not an array or primitive.","Verify the default export is actually reached (no early return / re-export of a non-config)."],"exampleFix":"// before\nexport default [reactPlugin]\n// after\nimport { defineConfig } from 'vite'\nexport default defineConfig({ plugins: [reactPlugin] })","handlingStrategy":"type-guard","validationCode":"import { isObject } from 'vite'\nconst cfg = typeof configExport === 'function' ? await configExport(env) : configExport\nif (!isObject(cfg)) throw new Error('Config must export/return a plain object')","typeGuard":"function isConfigObject(value: unknown): value is Record<string, any> {\n  return typeof value === 'object' && value !== null && !Array.isArray(value)\n}","tryCatchPattern":null,"preventionTips":["Always export a plain object (or use defineConfig) from vite.config.","If using a function config, ensure it returns an object, not an array or primitive.","Lint the config file to confirm a valid default export."],"tags":["config","validation","config-file"],"analyzedSha":"89620f09afcfef6b35e7bb8660132ab5b4d0cd3b","analyzedAt":"2026-08-03T19:28:02.920Z","schemaVersion":2}