Astro shows “Duplicate content entry slug” when two entries in the same collection end up with the same id. The message names the collection and the clashing value, saying entries “contains multiple entries with the same slug” and that “Slugs must be unique.” Because ids become URLs, two entries can’t share one. Find the two files and make their ids different.
Key Takeaways
- Ids come from file paths, or from a
slugfield in frontmatter if you set one.- Two files with the same
slugfrontmatter clash even in different folders.post.mdandpost.mdxside by side produce the same id.- Copies like
post copy.mdor backups left in the content folder cause it too.
Find the duplicates
The error tells you the slug. Search for it:
grep -rln "^slug: launch" src/content/blog/
ls src/content/blog/ | grep -i launch
The usual causes
Same slug in frontmatter
# src/content/blog/2025/launch.md
slug: launch
# src/content/blog/2026/launch.md
slug: launch
Folders don’t help when the slug is set explicitly. Make them unique (launch-2025, launch-2026), and add redirects if either URL was already public.
Same name, different extension
pricing.md and pricing.mdx both become pricing. Delete the one you converted from.
Stray copies
Editors and file sync tools leave launch (1).md or launch.backup.md. Exclude them with your glob() pattern or delete them. A pattern that skips underscore-prefixed files keeps drafts out cleanly:
loader: glob({ pattern: '**/[^_]*.{md,mdx}', base: './src/content/blog' }),
Then rename work-in-progress files to _draft-name.md.
Custom generateId
If you pass generateId to glob(), make sure it can’t produce the same value for two files, for example by only using the file’s base name while ignoring folders:
// Can collide: guides/setup.md and tutorials/setup.md both give "setup"
generateId: ({ entry }) => entry.split('/').pop()!.replace(/\.mdx?$/, ''),
Keep the folder in the id, or add a prefix.
Catch it before it ships
The error stops the build, so CI catches it. To check locally after reorganising content, run npm run build or npx astro sync.
Related: a schema can’t define slug as a field; see Content schema should not contain slug. For how ids work, read the Astro content collections guide, and the content docs for Komal themes for where theme content lives. The glob loader reference documents generateId.
FAQ
Can two different collections have the same id?
Yes. Ids only need to be unique within one collection.
Does Astro use the slug frontmatter field as the id?
Yes, the glob() loader uses a slug frontmatter value as the entry’s id when present.