Astro shows “Attempted to render an undefined content collection entry” when you call render() on something that is undefined, almost always the result of a getEntry() call that didn’t find an entry. The hint is direct: “Check if the entry is undefined before passing it to render().” Fix the id you’re looking up, and guard the call so a missing entry produces a 404 instead of a crash.
Key Takeaways
getEntry('blog', id)returnsundefinedfor an unknown id; it doesn’t throw.- Ids come from file paths:
blog/2026/launch.mdis2026/launch.- Guard with
if (!entry)beforerender(entry).- In static routes, pass the entry through
propsso there’s no lookup to get wrong.
Where it usually happens
---
// src/pages/blog/[slug].astro (on-demand)
export const prerender = false;
import { getEntry, render } from 'astro:content';
const entry = await getEntry('blog', Astro.params.slug!);
const { Content } = await render(entry); // entry is undefined for unknown slugs
---
Fix 1: guard and return a 404
---
export const prerender = false;
import { getEntry, render } from 'astro:content';
const entry = await getEntry('blog', Astro.params.slug!);
if (!entry) {
return new Response(null, { status: 404, statusText: 'Not found' });
}
const { Content } = await render(entry);
---
<h1>{entry.data.title}</h1>
<Content />
An empty 404 response makes Astro render your custom 404 page; the custom 404 page tip shows how to build one.
Fix 2: pass entries as props in static routes
For prerendered pages, look up nothing at render time:
---
import { getCollection, render } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map((post) => ({ params: { slug: post.id }, props: { post } }));
}
const { post } = Astro.props;
const { Content } = await render(post);
---
Every page receives a real entry, so the error can’t happen.
Fix 3: check the id
Log what exists:
const ids = (await getCollection('blog')).map((p) => p.id);
console.log(ids);
Common mismatches:
- Subfolders. The id includes the folder:
guides/setup, notsetup. - Extensions. Ids don’t include
.md. - Custom slugs. If a file sets
slugin frontmatter, that value is the id. - Old
slughabits. Code from older Astro versions may still passentry.slug, which no longer exists.
References
reference() fields resolve with getEntry(post.data.author). If a referenced entry was deleted, the schema catches it at build time, so this error points at code paths that build ids by hand.
The Astro content collections guide explains ids, getEntry() and render() in full. Related: Duplicate content entry slug. The official entry is in the Astro error reference.
FAQ
Does getEntry() throw if the entry doesn’t exist?
No. It returns undefined, so always check the result.
Why does it work in dev but fail in the build?
Usually an entry filtered out in one place (drafts hidden in production) but still linked or looked up elsewhere.