What Causes This Error?
This error occurs when you try to call render() on a content collection entry that is undefined. This usually happens when getEntry() doesn’t find a matching entry or when accessing an entry that doesn’t exist.
The Problem
---
import { getEntry } from 'astro:content';
// Entry doesn't exist
const post = await getEntry('blog', 'non-existent-slug');
// ❌ post is undefined, can't render
const { Content } = await post.render();
---
The Fix
Check Entry Exists
---
import { getEntry } from 'astro:content';
const post = await getEntry('blog', 'my-post');
// ✅ Check before rendering
if (!post) {
return Astro.redirect('/404');
}
const { Content } = await post.render();
---
<Content />
Use Optional Chaining
---
import { getEntry } from 'astro:content';
const post = await getEntry('blog', 'my-post');
// ✅ Guard against undefined
const rendered = post ? await post.render() : null;
---
{rendered ? <rendered.Content /> : <p>Post not found</p>}
Common Scenarios
Dynamic Routes
---
// src/pages/blog/[slug].astro
import { getCollection, getEntry } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
// ✅ Use props from getStaticPaths - guaranteed to exist
const { post } = Astro.props;
const { Content } = await post.render();
---
<Content />
Manual Entry Lookup
---
import { getEntry } from 'astro:content';
const slug = Astro.params.slug;
const post = await getEntry('blog', slug);
// ✅ Handle missing entry
if (!post) {
return new Response(null, {
status: 404,
statusText: 'Not Found',
});
}
const { Content } = await post.render();
---
Server-Side Rendering
---
// With SSR, slug might not exist
export const prerender = false;
import { getEntry } from 'astro:content';
const { slug } = Astro.params;
const post = await getEntry('blog', slug);
if (!post) {
return Astro.redirect('/404');
}
const { Content } = await post.render();
---
Referencing Related Entries
---
import { getEntry } from 'astro:content';
const post = await getEntry('blog', 'my-post');
const authorId = post?.data.author;
// ✅ Check related entry exists
const author = authorId
? await getEntry('authors', authorId)
: null;
if (author) {
console.log(author.data.name);
}
---
Collection with Filter
---
import { getCollection } from 'astro:content';
// Filter might return empty array
const featuredPosts = await getCollection('blog', (entry) =>
entry.data.featured === true
);
// ✅ Check array has items
if (featuredPosts.length === 0) {
return <p>No featured posts</p>;
}
// Safe to access first item
const firstFeatured = featuredPosts[0];
const { Content } = await firstFeatured.render();
---
TypeScript Safety
---
import { getEntry, type CollectionEntry } from 'astro:content';
const post = await getEntry('blog', 'my-post');
// TypeScript knows post might be undefined
// Use type guard
function isDefined<T>(value: T | undefined): value is T {
return value !== undefined;
}
if (isDefined(post)) {
const { Content } = await post.render();
// TypeScript knows post is defined here
}
---
Debugging Missing Entries
---
import { getCollection, getEntry } from 'astro:content';
// List all available entries
const allPosts = await getCollection('blog');
console.log('Available slugs:', allPosts.map(p => p.slug));
// Try to get entry
const post = await getEntry('blog', 'my-slug');
console.log('Found post:', post ? 'yes' : 'no');
---
Quick Checklist
- Always check if
getEntry()returns undefined - Use
getStaticPathsprops for guaranteed entries - Redirect to 404 for missing entries
- Check array length before accessing items
- Log available slugs to debug issues