withastro/astro · error · AstroError
InvalidGetStaticPathsReturn
InvalidGetStaticPathsReturn
Error message
Invalid type returned by `getStaticPaths()`. Expected an `array`, got `${returnType}`. What it means
getStaticPaths() must return a plain array of { params, props } entry objects. validateGetStaticPathsResult checks Array.isArray on the returned value and throws InvalidGetStaticPathsReturn (with typeof interpolated into the message) when it is anything else — an object map, a string, undefined, a Promise-like that was not awaited, etc. The route params cannot be derived from a non-array shape.
Solutions
- Make the function return an array: wrap object values with Object.values(map).map(...) or ensure every code path returns the array.
- If getStaticPaths is async, await all async calls before returning (return (await getPosts()).map(...)).
- Return [] (empty array) explicitly when the collection is empty, instead of undefined.
Example fix
// before
export async function getStaticPaths() {
const res = fetch('https://api.example.com/posts'); // missing await
return res.json().map((p) => ({ params: { slug: p.slug } }));
}
// after
export async function getStaticPaths() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
return posts.map((p) => ({ params: { slug: p.slug } }));
} Defensive patterns
Strategy: type-guard
Type guard
type StaticPath = { params: Record<string, string | undefined>; props?: Record<string, unknown> };
function isStaticPathArray(v: unknown): v is StaticPath[] {
return (
Array.isArray(v) &&
v.every((e) => typeof e === 'object' && e !== null && !Array.isArray(e) && 'params' in e)
);
}
// const paths = await getStaticPaths();
// if (!isStaticPathArray(paths)) throw new TypeError('getStaticPaths must return { params }[]'); Prevention
- Always return an array; convert keyed maps with Object.values(...).map(...).
- Ensure every branch of getStaticPaths returns (no bare early exits).
- Await async data before returning so a Promise never leaks out.
When it happens
Trigger: Returning an object keyed by slug (return { 'a': {...}, 'b': {...} }); returning a single entry instead of a list (return { params: { slug: 'a' } }); forgetting await on an async fetch inside getStaticPaths so a Promise leaks; returning undefined because of a missing return in an if-branch; returning a Map or generator.
Common situations: Porting data from a CMS keyed as an object; early-return code paths that forget to return; getStaticPaths declared async but the final .map() chain dropped; returning getCollection(...) directly thinking it is an array.
Related errors
- GetStaticPathsExpectedParams
- InvalidGetStaticPathsEntry
- getStaticPaths() ignored in dynamic page
- GetStaticPathsRequired
- Astro.generator inside getStaticPaths is deprecated and…
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/c8986241aeddde7d.
Report an issue: GitHub.
Appendix: source
Thrown at packages/astro/src/core/routing/validation.ts:28
ssr,
route,
}: {
ssr: boolean;
route: RouteData;
},
) {
if ((!ssr || route.prerender) && route.origin !== 'internal' && !mod.getStaticPaths) {
throw new AstroError({
...AstroErrorData.GetStaticPathsRequired,
location: { file: route.component },
});
}
}
/** Throw error and log warnings for malformed getStaticPaths() response */
export function validateGetStaticPathsResult(result: GetStaticPathsResult, route: RouteData) {
if (!Array.isArray(result)) {
throw new AstroError({
...AstroErrorData.InvalidGetStaticPathsReturn,
message: AstroErrorData.InvalidGetStaticPathsReturn.message(typeof result),
location: {
file: route.component,
},
});
}
result.forEach((pathObject) => {
if ((typeof pathObject === 'object' && Array.isArray(pathObject)) || pathObject === null) {
throw new AstroError({
...AstroErrorData.InvalidGetStaticPathsEntry,
message: AstroErrorData.InvalidGetStaticPathsEntry.message(
Array.isArray(pathObject) ? 'array' : typeof pathObject,
),
});
}
View on GitHub (pinned to 52e6c34790)