vercel/next.js · error
Default export is missing in {resource_path}
Error message
Default export is missing in {resource_path} What it means
Emitted at request time inside the JavaScript that Turbopack generates for a text-based App Router metadata route (e.g. app/robots.ts, app/manifest.ts, app/sitemap.xml without generateSitemaps, app/icon). The generated wrapper imports the route module's default export as `handler` and checks `typeof handler !== 'function'`; if the file has no default-exported function, it throws. Metadata route handlers must default-export a function that returns the route's data.
Source
Thrown at crates/next-core/src/next_app/metadata/route.rs:236
let stem = stem.unwrap_or_default();
let content_type = get_content_type(path.clone()).await?;
// refer https://github.com/vercel/next.js/blob/7b2b9823432fb1fa28ae0ac3878801d638d93311/packages/next/src/build/webpack/loaders/next-metadata-route-loader.ts#L84
// for the original template.
let code = formatdoc! {
r#"
import {{ NextResponse }} from 'next/server'
import handler from {resource_path}
import {{ resolveRouteData }} from
'next/dist/build/webpack/loaders/metadata/resolve-route-data'
const contentType = {content_type}
const cacheControl = {cache_control}
const fileType = {file_type}
if (typeof handler !== 'function') {{
throw new Error('Default export is missing in {resource_path}')
}}
export async function GET() {{
const data = await handler()
const content = resolveRouteData(data, fileType)
return new NextResponse(content, {{
headers: {{
'Content-Type': contentType,
'Cache-Control': cacheControl,
}},
}})
}}
export * from {resource_path}
"#,
resource_path = StringifyJs(&format!("./{}", path.file_name())),
content_type = StringifyJs(&content_type),View on GitHub (pinned to 0ae8c72462)
Solutions
- Add a default-exported function to the metadata route file that returns the route data.
- Confirm the file is a recognized metadata route (correct filename: robots, manifest, sitemap, icon, apple-icon, etc.).
- Ensure the default export is a function, not an object or constant.
Example fix
// before: app/robots.ts
export const metadata = { rules: [] }
// after: app/robots.ts
export default function(): MetadataRoute.Robots {
return { rules: [{ userAgent: '*', allow: '/' }] }
} Defensive patterns
Strategy: validation
Validate before calling
// Validate a metadata route file has a default function export at author time
// (run in a lint rule or pre-build check)
function assertMetadataDefaultExport(moduleSource: string, file: string) {
if (!/export\s+default\s+(async\s+)?function/.test(moduleSource)) {
throw new Error(`${file}: metadata route must default-export a function`)
}
} Type guard
const isFunction = (v: unknown): v is (...a: any[]) => any => typeof v === 'function'
Try / catch
null
Prevention
- Always default-export a function from metadata route files (robots, manifest, sitemap, icon).
- Use the MetadataRoute.* TypeScript types which enforce the function signature.
- Add a lint rule that flags metadata route files missing a default function export.
When it happens
Trigger: A metadata route file (app/robots.ts, app/manifest.ts, app/sitemap.xml, app/<name>.txt) that exports only named exports, has no default export, or default-exports a non-function (object, string).
Common situations: Copying a Pages Router API route pattern (named exports); writing a config object instead of a function; forgetting the default export; refactoring that renamed/removed it.
Related errors
- id property is required for every item returned from generat
- id property is required for every item returned from generat
- Page with dynamic = "error" encountered dynamic data method
- gave up applying effects after {MAX_RETRIES} retries; repeat
- Command failed: ${command} ${args.join(' ')} (exit ${code})
AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06).
Data as JSON: /api/errors/4a0340db15724b87.
Report an issue: GitHub.