withastro/astro · error · AstroError
UnknownContentCollectionError
UnknownContentCollectionError
Error message
Unknown content collection error.
What it means
During content sync, Astro reads each discovered entry file from disk. If fs.readFile rejects — the file vanished between discovery and read, permissions block it, or a symlink is broken — the failure is rethrown as UnknownContentCollectionError with the original error attached as cause.
Solutions
- Re-run the build or wait for the next dev-server sync — transient races during file churn usually clear.
- Check that the file exists and is readable; look for broken symlinks in src/content.
- Fix permissions or mounts if the error persists, then restart astro dev.
- If reproducible, inspect error.cause for the underlying errno (ENOENT vs EACCES) to narrow it down.
Defensive patterns
Strategy: retry
Validate before calling
// Before batch operations, verify every entry file still exists
import { existsSync } from 'node:fs';
import { join } from 'node:path';
const missing = expectedEntryPaths.filter((p) => !existsSync(join('src/content', p)));
if (missing.length) throw new Error(`entries vanished: ${missing.join(', ')}`); Try / catch
// Transient during watch; retry once before surfacing
try {
await syncContent();
} catch (e) {
if (e instanceof Error && e.cause && e.cause.code === 'ENOENT') {
await new Promise((r) => setTimeout(r, 500));
await syncContent(); // file churn usually settles
} else throw e;
} Prevention
- Avoid switching branches or bulk-moving content while astro dev or a build is running.
- Commit and pull content changes with the dev server stopped.
- Check file permissions and symlinks in src/content when the error persists.
- Inspect error.cause for the real errno before assuming data corruption.
When it happens
Trigger: An entry file deleted or renamed while a build or dev-server watch sync is in progress; unreadable file permissions; broken symlinks inside src/content; content stored on flaky network mounts.
Common situations: Switching git branches while astro dev watches content; editors doing atomic save-replace exactly as sync runs; Docker volume permission mismatches; CI caches restoring stale trees.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Collection loader for
- Error when reading content directory
- No contents found for
- ** ** contains invalid content
- The base directory " " does not exist.
AI-assisted analysis of withastro/astro@e294953aa8 (2026-08-18).
Data as JSON: /api/errors/24b9feb43bfea64a.
Report an issue: GitHub.
Appendix: source
Thrown at packages/astro/src/content/utils.ts:837
collection,
generatedSlug,
contentEntryType,
fileUrl,
fs,
}: {
fs: typeof fsMod;
id: string;
collection: string;
generatedSlug: string;
fileUrl: URL;
contentEntryType: Pick<ContentEntryType, 'getEntryInfo'>;
}) {
let contents: string;
try {
contents = await fs.promises.readFile(fileUrl, 'utf-8');
} catch (e) {
// File contents should exist. Raise unexpected error as "unknown" if not.
throw new AstroError(AstroErrorData.UnknownContentCollectionError, { cause: e });
}
const { slug: frontmatterSlug } = await contentEntryType.getEntryInfo({
fileUrl,
contents,
});
return parseEntrySlug({ generatedSlug, frontmatterSlug, id, collection });
}
function getExtGlob(exts: string[]) {
return exts.length === 1
? // Wrapping {...} breaks when there is only one extension
exts[0]
: `{${exts.join(',')}}`;
}
function globWithUnderscoresIgnored(relContentDir: string, exts: string[]): string[] {
const extGlob = getExtGlob(exts);
const contentDir = relContentDir.length > 0 ? appendForwardSlash(relContentDir) : relContentDir;View on GitHub (pinned to e294953aa8)