{"record":{"id":"2b7907df301ee2d1","repo":"vercel/next.js","slug":"specified-distdir-is-not-a-string-found-type-t","errorCode":null,"errorMessage":"Specified distDir is not a string, found type \"${typeof value}\"","messagePattern":"Specified distDir is not a string, found type \"(.+?)\"","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/next/src/server/config.ts","lineNumber":345,"sourceCode":"      )\n    }\n    if (typeof userConfig.trailingSlash === 'undefined') {\n      userConfig.trailingSlash = (userConfig as any).exportTrailingSlash\n    }\n    delete (userConfig as any).exportTrailingSlash\n  }\n\n  const config = Object.keys(userConfig).reduce<{ [key: string]: any }>(\n    (currentConfig, key) => {\n      const value = (userConfig as any)[key]\n\n      if (value === undefined || value === null) {\n        return currentConfig\n      }\n\n      if (key === 'distDir') {\n        if (typeof value !== 'string') {\n          throw new Error(\n            `Specified distDir is not a string, found type \"${typeof value}\"`\n          )\n        }\n        const userDistDir = value.trim()\n\n        // don't allow public as the distDir as this is a reserved folder for\n        // public files\n        if (userDistDir === 'public') {\n          throw new Error(\n            `The 'public' directory is reserved in Next.js and can not be set as the 'distDir'. https://nextjs.org/docs/messages/can-not-output-to-public`\n          )\n        }\n        // make sure distDir isn't an empty string as it can result in the provided\n        // directory being deleted in development mode\n        if (userDistDir.length === 0) {\n          throw new Error(\n            `Invalid distDir provided, distDir can not be an empty string. Please remove this config or set it to undefined`\n          )","sourceCodeStart":327,"sourceCodeEnd":363,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/packages/next/src/server/config.ts#L327-L363","documentation":"Thrown during config normalization when the distDir option is present but not a string. distDir tells Next.js where to emit the build output (.next by default); it must be a string path. Any other type (number, object, array, boolean) is rejected outright before further validation (reserved-name, empty-string checks).","triggerScenarios":"next.config.js sets distDir to a non-string value (e.g. distDir: true, distDir: 123, or a variable that resolved to undefined-ish/non-string). The reduce loop at config.ts:343 checks typeof value !== 'string' and throws.","commonSituations":"Programmatic config computing distDir from an env var that is undefined (resulting in a non-string); accidentally assigning an object; typos; a conditional that yields a boolean.","solutions":["Set distDir to a string path, e.g. '.next' or 'build'.","If deriving from an env var, coerce/guard: distDir: process.env.OUT_DIR || '.next'.","Remove the distDir key entirely to use the default '.next'.","Verify the config file does not assign a non-string to distDir under any branch."],"exampleFix":"// before\n// module.exports = { distDir: process.env.OUT_DIR } // OUT_DIR unset -> undefined\n\n// after\n// module.exports = { distDir: process.env.OUT_DIR || '.next' }","handlingStrategy":"type-guard","validationCode":"// Coerce distDir to a safe string default.\nconst raw = (config as any).distDir\nif (raw !== undefined && typeof raw !== 'string') {\n  throw new Error('distDir must be a string')\n}\nconfig.distDir = typeof raw === 'string' ? raw : '.next'","typeGuard":"function isStringDistDir(v: unknown): v is string | undefined {\n  return v === undefined || typeof v === 'string'\n}","tryCatchPattern":null,"preventionTips":["Always derive distDir with a string fallback (|| '.next').","Avoid assigning non-strings to distDir under any config branch.","Omit distDir to accept the default.","Type your next.config to surface type errors for bad values."],"tags":["configuration","next-config","build-output","validation"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}