withastro/astro · error · TypeError
maxDuration must be a number
Error message
maxDuration must be a number
What it means
The Vercel adapter validates the maxDuration option (serverless function timeout in seconds) as soon as the integration is created: a truthy value that is not a number, such as a string pulled from an environment variable, throws a TypeError carrying the bad value as cause.
Solutions
- Pass a plain positive number: maxDuration: 30
- Convert env strings: maxDuration: Number(process.env.MAX_DURATION)
- Guard optional values so undefined (option omitted) is passed instead of 'undefined' or NaN
Example fix
// before
vercel({ maxDuration: process.env.MAX_DURATION })
// after
vercel({ maxDuration: Number(process.env.MAX_DURATION) }) Defensive patterns
Strategy: type-guard
Validate before calling
const raw = process.env.MAX_DURATION;
const maxDuration = raw === undefined ? undefined : Number(raw);
if (maxDuration !== undefined && (!Number.isFinite(maxDuration) || maxDuration <= 0)) {
throw new Error('MAX_DURATION must be a positive number of seconds');
}
vercel({ maxDuration }) Type guard
function isPositiveNumber(v: unknown): v is number {
return typeof v === 'number' && Number.isFinite(v) && v > 0;
} Prevention
- Coerce env-sourced options with Number() before passing them to the adapter
- Keep numeric adapter options numeric in config files (avoid quoted YAML values)
- Validate the whole adapter options object in a preflight check
When it happens
Trigger: Passing vercel({ maxDuration: '30' }), maxDuration: process.env.MAX_DURATION (always a string), or another non-number truthy value; a companion check also rejects numbers <= 0.
Common situations: Wiring the timeout from an env var or orchestrator config without converting types; config files authored as JSON/YAML where numbers arrive as strings.
Related errors
- Vercel Image Optimization requires at least one size to be…
- Your "vercel.json" config is not a valid json file.
- Apps must be an object with an id, a name and an entrypoint.
- [astro] deprecated. Move onto your processor instead (e.g…
- `Astro.session` was accessed but no session storage is…
AI-assisted analysis of withastro/astro@3578d45d34 (2026-08-18).
Data as JSON: /api/errors/7d7c7930f46ed9c4.
Report an issue: GitHub.
Appendix: source
Thrown at packages/integrations/vercel/src/index.ts:255
webAnalytics,
includeFiles: _includeFiles = [],
excludeFiles: _excludeFiles = [],
imageService,
imagesConfig,
devImageService = 'sharp',
middlewareMode,
edgeMiddleware,
maxDuration,
isr = false,
skewProtection = process.env.VERCEL_SKEW_PROTECTION_ENABLED === '1',
staticHeaders = false,
}: VercelServerlessConfig = {}): AstroIntegration {
// Resolve middleware mode with backward compatibility
const resolvedMiddlewareMode = middlewareMode ?? (edgeMiddleware ? 'edge' : 'classic');
if (maxDuration) {
if (typeof maxDuration !== 'number') {
throw new TypeError(`maxDuration must be a number`, {
cause: maxDuration,
});
}
if (maxDuration <= 0) {
throw new TypeError(`maxDuration must be a positive number`, {
cause: maxDuration,
});
}
}
let _config: AstroConfig;
let _buildTempFolder: URL;
let _serverEntry: string;
let _middlewareEntryPoint: URL | undefined;
let _hasServerBuild = false;
let _routeToHeaders: RouteToHeaders | undefined = undefined;
// Extra files to be merged with `includeFiles` during build
const extraFilesToInclude: URL[] = [];View on GitHub (pinned to 3578d45d34)