withastro/astro · error · AstroError
RenderUndefinedEntryError
RenderUndefinedEntryError
Error message
Attempted to render an undefined content collection entry.
What it means
renderEntry() backs the public render(entry) from astro:content and throws this error when it receives a falsy entry. getEntry and getCollection lookups return undefined for ids/slugs that do not exist, so rendering without a check turns a missing entry into this explicit error rather than a cryptic crash inside the renderer.
Solutions
- Check the entry before rendering and return a 404 or redirect: if (!post) return Astro.redirect('/404').
- Verify the identifier you pass matches how entries are keyed: id for data entries, slug for content entries.
- For dynamic routes, generate params from getCollection()/getStaticPaths so only existing entries render.
Example fix
// before
const post = await getEntry('blog', params.slug);
const { Content } = await render(post);
// after
const post = await getEntry('blog', params.slug);
if (!post) return Astro.redirect('/404');
const { Content } = await render(post); Defensive patterns
Strategy: type-guard
Validate before calling
// Always resolve and check before rendering
const post = params.slug ? await getEntry('blog', params.slug) : undefined;
if (!post) return Astro.redirect('/404');
const { Content } = await render(post); Type guard
import type { CollectionEntry } from 'astro:content';
function isRenderableEntry<E>(entry: E | undefined | null): entry is E {
return entry != null;
}
// usage
if (isRenderableEntry(post)) await render(post); Prevention
- Treat every getEntry/getEntryBySlug call as possibly returning undefined.
- In dynamic routes, derive params from the collection itself via getStaticPaths so missing entries cannot reach render().
- Enable strict TS settings (strictNullChecks) so undefined results surface at compile time.
When it happens
Trigger: Calling render(entry) where entry came from getEntry('blog', id) and no entry with that id/slug exists; dynamic routes ([...slug].astro) where params.slug matches no entry; entries removed or renamed between data sync and render.
Common situations: Dynamic routes without a getStaticPaths guard; typo'd slug from a URL parameter; content deleted during a CMS migration while pages still reference it; code assuming getEntry throws on miss instead of returning undefined.
Related errors
- A content collection is defined with legacy features (e.g…
- An error was encountered while creating the JSON schema for…
- Auto-generating collections for folders in "src/content/"…
- ** ** contains multiple entries with the same slug: ` `…
- ** ** contains multiple entries with the same slug: ` `…
AI-assisted analysis of withastro/astro@e294953aa8 (2026-09-09).
Data as JSON: /api/errors/9e05fa148128ce87.
Report an issue: GitHub.
Appendix: source
Thrown at packages/astro/src/content/runtime.ts:626
const resolved = resolveImageAtPath(src, fileName, imageAssetMap);
if (resolved !== undefined) {
result = setAtPathCopying(result, path, resolved);
}
}
return result;
}
export function resolveEntryData<T extends Record<string, unknown>>(
entry: DataEntry<T>,
imageAssetMap?: Map<string, ImageMetadata>,
): T {
return updateImageReferencesInData(entry.data, entry.filePath, imageAssetMap, entry.imageImports);
}
export function createRenderEntry({ logger }: { logger: AstroLogger }) {
return async function renderEntry(entry: DataEntry) {
if (!entry) {
throw new AstroError(AstroErrorData.RenderUndefinedEntryError);
}
recordContentEntryRender(entry.filePath);
if (entry.deferredRender) {
try {
// @ts-expect-error virtual module
const { default: contentModules } = await import('astro:content-module-imports');
const renderEntryImport = contentModules.get(entry.filePath);
return render({
collection: '',
id: entry.id,
renderEntryImport,
});
} catch (e) {
logger.error('content', `${e}`);
}
}
View on GitHub (pinned to e294953aa8)