withastro/astro · warning
Entry ${collection} → ${lookupId} was not found.
Error message
Entry ${collection} → ${lookupId} was not found. What it means
getEntry(collection, lookupId) found the collection but no entry with that id; Astro logs this warning and returns undefined. Note the API accepts ids and, for content entries, slugs — passing an object as the identifier is a separate hard error above this branch, but a stale or wrong string only yields undefined plus this warning, which frequently surfaces later as a TypeError on the undefined result.
Source
Thrown at packages/astro/src/content/runtime.ts:215
if (collection in liveCollections) {
throw new AstroError({
...AstroErrorData.UnknownContentCollectionError,
message: `Collection "${collection}" is a live collection. Use getLiveEntry() instead of getEntry().`,
});
}
if (typeof lookupId === 'object') {
throw new AstroError({
...AstroErrorData.UnknownContentCollectionError,
message: `The entry identifier must be a string. Received object.`,
});
}
const store = await globalDataStore.get();
if (await store.hasCollection(collection)) {
const entry = await store.get<DataEntry>(collection, lookupId);
if (!entry) {
logger.warn('content', `Entry ${collection} → ${lookupId} was not found.`);
return;
}
// @ts-expect-error virtual module
const { default: imageAssetMap } = await import('astro:asset-imports');
const data = resolveEntryData(entry, imageAssetMap);
const result = {
...entry,
data,
collection,
} as DataEntryResult | ContentEntryResult;
// TODO: remove in Astro 8
warnForPropertyAccess(
logger,
result.data,
'slug',
`[content] Attempted to access deprecated property on "${collection}" entry.\nThe "slug" property is no longer automatically added to entries. Please use the "id" property instead.`,
);View on GitHub (pinned to e294953aa8)
Solutions
- Use the current id/slug — run astro sync and rely on generated types to flag stale references at compile time
- Guard the undefined result before accessing properties
- For dynamic routes, derive lookups from getStaticPaths so the ids always exist
Example fix
// before
const post = await getEntry('blog', 'old-slug');
const { data } = post; // TypeError when undefined
// after
const post = await getEntry('blog', 'new-slug');
if (!post) return null;
const { data } = post; Defensive patterns
Strategy: type-guard
Validate before calling
// For dynamic routes, validate ids against the store before lookup
const entries = await getCollection('blog');
const ids = new Set(entries.map((e) => e.id));
if (!ids.has(lookupId)) {
return Astro.redirect('/404');
} Type guard
type ContentEntryLike = { id: string; slug: string };
function isEntry<T extends ContentEntryLike>(entry: T | undefined): entry is T {
return entry !== undefined;
}
// usage:
const post = await getEntry('blog', slug);
if (!isEntry(post)) return Astro.redirect('/404'); Prevention
- Prefer getEntries with ids from getStaticPaths so lookups cannot drift
- Always branch on the undefined return of getEntry before property access
- Run astro sync and use generated entry types to catch stale slugs at compile time
When it happens
Trigger: Looking up a hard-coded slug/id that was renamed or deleted; confusing data-entry ids with content-entry slugs; entries whose frontmatter slug differs from the filename so the wrong key is passed.
Common situations: Renaming files or slugs breaking getEntry calls scattered through pages; lookups driven by URL params or CMS data; dynamic routes whose param values drift from actual entry ids.
Related errors
- The collection ${JSON.stringify(collection)} does not exist
- [content] Could not read the chunked data store at ${fileURL
- No items found in ${fileName}
- **${collection}** contains multiple entries with the same sl
- SessionStorageInitError
AI-assisted analysis of withastro/astro@e294953aa8 (2026-09-09).
Data as JSON: /api/errors/554b5de6e48bb652.
Report an issue: GitHub.