withastro/astro · error · AstroError
UnknownContentCollectionError
UnknownContentCollectionError
Error message
Unexpected error reading entry ${fileId}. What it means
Thrown when `fs.promises.readFile` fails while reading a content entry file inside `getEntryModuleBaseInfo` in the content imports Vite plugin. Unlike error 103, this path attaches the original stack trace rather than using `cause`. It wraps any filesystem read failure as `UnknownContentCollectionError` with a message containing the file ID.
Source
Thrown at packages/astro/src/content/vite-plugin-content-imports.ts:347
};
return dataEntryModule;
}
// Shared logic for `getContentEntryModule` and `getDataEntryModule`
// Extracting to a helper was easier that conditionals and generics :)
async function getEntryModuleBaseInfo<TEntryType extends ContentEntryType | DataEntryType>({
fileId,
entryConfigByExt,
contentDir,
fs,
}: GetEntryModuleParams<TEntryType>) {
const contentConfig = await getContentConfigFromGlobal();
let rawContents;
try {
rawContents = await fs.promises.readFile(fileId, 'utf-8');
} catch (e) {
throw new AstroError({
...AstroErrorData.UnknownContentCollectionError,
message: `Unexpected error reading entry ${JSON.stringify(fileId)}.`,
stack: e instanceof Error ? e.stack : undefined,
});
}
const fileExt = extname(fileId);
const entryConfig = entryConfigByExt.get(fileExt);
if (!entryConfig) {
throw new AstroError({
...AstroErrorData.UnknownContentCollectionError,
message: `No parser found for data entry ${JSON.stringify(
fileId,
)}. Did you apply an integration for this file type?`,
});
}
const entry = pathToFileURL(fileId);
const collection = getEntryCollectionName({ entry, contentDir });View on GitHub (pinned to d081033d5f)
Solutions
- Check that the file ID in the JSON-stringified error message exists on disk.
- Restart the dev server to clear stale module graph entries.
- Fix filesystem permissions on the affected file.
- Ensure no external process (linter, formatter, sync tool) is deleting or locking content files during build.
Defensive patterns
Strategy: try-catch
Validate before calling
import { existsSync } from 'fs';
function preCheckEntry(fileId: string) {
if (!existsSync(fileId)) {
throw new Error(`Content entry missing before build: ${fileId}`);
}
} Try / catch
try {
await build();
} catch (e) {
if (e instanceof Error && e.message.includes('Unexpected error reading entry')) {
console.error('Stale Vite cache or deleted file:', e.message);
}
throw e;
} Prevention
- Restart the dev server after bulk content file operations.
- Avoid file-locking tools during builds.
- Use a pre-build script to verify all content files are present.
When it happens
Trigger: The content imports plugin's module resolution calls `getEntryModuleBaseInfo` for an entry ID. The `readFile` for that ID throws (ENOENT, EACCES, etc.), and the error is re-thrown as an AstroError with the original error's stack.
Common situations: HMR triggered for a file that was just deleted. File watcher fires for a temp file created by an editor. Permission denied on a content file. A virtual or stale module ID is passed after the source was renamed.
Related errors
- UnknownContentCollectionError
- UnknownFilesystemError
- ImageNotFound
- PluginContentImportsError
- CannotDetermineWeightAndStyleFromFontFile
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/9f89eac55ec2d9b6.
Report an issue: GitHub.