{"record":{"id":"aa475d6c3388555b","repo":"withastro/astro","slug":"maxduration-must-be-a-positive-number","errorCode":null,"errorMessage":"maxDuration must be a positive number","messagePattern":"maxDuration must be a positive number","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/integrations/vercel/src/index.ts","lineNumber":260,"sourceCode":"\tdevImageService = 'sharp',\n\tmiddlewareMode,\n\tedgeMiddleware,\n\tmaxDuration,\n\tisr = false,\n\tskewProtection = process.env.VERCEL_SKEW_PROTECTION_ENABLED === '1',\n\tstaticHeaders = false,\n}: VercelServerlessConfig = {}): AstroIntegration {\n\t// Resolve middleware mode with backward compatibility\n\tconst resolvedMiddlewareMode = middlewareMode ?? (edgeMiddleware ? 'edge' : 'classic');\n\n\tif (maxDuration) {\n\t\tif (typeof maxDuration !== 'number') {\n\t\t\tthrow new TypeError(`maxDuration must be a number`, {\n\t\t\t\tcause: maxDuration,\n\t\t\t});\n\t\t}\n\t\tif (maxDuration <= 0) {\n\t\t\tthrow new TypeError(`maxDuration must be a positive number`, {\n\t\t\t\tcause: maxDuration,\n\t\t\t});\n\t\t}\n\t}\n\n\tlet _config: AstroConfig;\n\tlet _buildTempFolder: URL;\n\tlet _serverEntry: string;\n\tlet _middlewareEntryPoint: URL | undefined;\n\tlet _hasServerBuild = false;\n\tlet _routeToHeaders: RouteToHeaders | undefined = undefined;\n\t// Extra files to be merged with `includeFiles` during build\n\tconst extraFilesToInclude: URL[] = [];\n\t// Secret used to verify that the caller is the astro-generated edge middleware and not a third-party\n\tconst middlewareSecret = crypto.randomUUID();\n\n\tlet _buildOutput: 'server' | 'static';\n","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/withastro/astro/blob/3578d45d34226d63cff3d261c971c221de6794d2/packages/integrations/vercel/src/index.ts#L242-L278","documentation":"The Vercel adapter validates its `maxDuration` option at integration setup, before any build work starts. `maxDuration` maps to the serverless function timeout written to the build output, so Vercel requires a number strictly greater than zero. This specific throw fires when the value is a number but is zero or negative (a preceding check handles non-number values).","triggerScenarios":"Calling `vercel({ maxDuration: 0 })` or `vercel({ maxDuration: -5 })` in astro.config.mjs. It also fires when the value comes from an env var parsed with Number() that resolves to 0 (e.g. `Number('')`), or from a computed expression that clamps to <= 0.","commonSituations":"Developers set `maxDuration: 0` intending \"no limit\" instead of omitting the option; config is copied between projects and the value is templated from CI variables that are empty; a preset/shared config object defaults maxDuration to 0.","solutions":["Set maxDuration to a positive integer (e.g. 10 or 60): `vercel({ maxDuration: 60 })`","Omit maxDuration entirely to use Vercel's default function timeout if you don't need a custom limit","If the value comes from an environment variable, parse and guard it: `const maxDuration = Number(process.env.MAX_DURATION) > 0 ? Number(process.env.MAX_DURATION) : undefined`"],"exampleFix":"// before\nexport default defineConfig({\n  adapter: vercel({ maxDuration: 0 }),\n});\n\n// after\nexport default defineConfig({\n  adapter: vercel({ maxDuration: 60 }),\n});","handlingStrategy":"validation","validationCode":"const maxDuration = Number(process.env.VERCEL_MAX_DURATION);\nexport default defineConfig({\n  adapter: vercel({\n    maxDuration: Number.isFinite(maxDuration) && maxDuration > 0 ? maxDuration : undefined,\n  }),\n});","typeGuard":"function isValidMaxDuration(v: unknown): v is number {\n  return typeof v === 'number' && v > 0;\n}","tryCatchPattern":null,"preventionTips":["Keep adapter options as literals in astro.config.mjs instead of templating from env vars","Run `astro build` in CI to catch config validation before deploy","Remember 0 does not mean 'unlimited' — omit maxDuration for the platform default"],"tags":["vercel","adapter","config-validation","maxduration"],"backgroundTag":"invalid-config-value","analyzedSha":"3578d45d34226d63cff3d261c971c221de6794d2","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}