withastro/astro · error · AstroError

UnknownContentCollectionError

UnknownContentCollectionError

Error message

Unexpected error reading entry ${JSON.stringify(fileId)}.

What it means

vite-plugin-content-imports generates a module per entry when astro:content imports are requested in dev or build. Before emitting the module it reads the raw entry file; a read failure is wrapped as UnknownContentCollectionError with the underlying stack attached.

Solutions

  1. Restore the file or stop importing it, then reload — the dev server regenerates entry modules on demand.
  2. Restart the dev server to clear the stale module graph.
  3. Verify the path printed in the error exists and is readable.
  4. If it recurs on every save, exclude src/content from antivirus scanning or tune watcher debounce.
Defensive patterns

Strategy: retry

Validate before calling

// Guard code that imports entries by id: confirm the file exists first
import { existsSync } from 'node:fs';
import { join } from 'node:path';
function assertEntryFile(collectionDir, id) {
  const p = join(collectionDir, id);
  if (!existsSync(p)) throw new Error(`entry file gone: ${p}`);
}

Try / catch

// In dev, a reload usually regenerates the module after file churn
try {
  await import('astro:content');
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Unexpected error reading entry')) {
    // restart/reload dev server, then retry the import
    throw new Error('entry file unreadable — restore it and reload the dev server', { cause: e });
  }
  throw e;
}

Prevention

When it happens

Trigger: The dev server holds a module for an entry that was just deleted or moved while an open page still imports it; file permissions or locking (antivirus on Windows); partial writes racing the watcher.

Common situations: Renaming/removing content entries while astro dev runs; editor atomic saves; monorepo watchers firing on half-written files; paths with characters the filesystem rejects.

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


AI-assisted analysis of withastro/astro@e294953aa8 (2026-08-18). Data as JSON: /api/errors/9f89eac55ec2d9b6. Report an issue: GitHub.

Appendix: source

Thrown at packages/astro/src/content/vite-plugin-content-imports.ts:348

	};

	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 e294953aa8)