{"record":{"id":"9f89eac55ec2d9b6","repo":"withastro/astro","slug":"unknowncontentcollectionerror-9f89ea","errorCode":"UnknownContentCollectionError","errorMessage":"Unexpected error reading entry ${fileId}.","messagePattern":"Unexpected error reading entry (.+?)\\.","errorType":"error_code","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/content/vite-plugin-content-imports.ts","lineNumber":347,"sourceCode":"\t};\n\n\treturn dataEntryModule;\n}\n\n// Shared logic for `getContentEntryModule` and `getDataEntryModule`\n// Extracting to a helper was easier that conditionals and generics :)\nasync function getEntryModuleBaseInfo<TEntryType extends ContentEntryType | DataEntryType>({\n\tfileId,\n\tentryConfigByExt,\n\tcontentDir,\n\tfs,\n}: GetEntryModuleParams<TEntryType>) {\n\tconst contentConfig = await getContentConfigFromGlobal();\n\tlet rawContents;\n\ttry {\n\t\trawContents = await fs.promises.readFile(fileId, 'utf-8');\n\t} catch (e) {\n\t\tthrow new AstroError({\n\t\t\t...AstroErrorData.UnknownContentCollectionError,\n\t\t\tmessage: `Unexpected error reading entry ${JSON.stringify(fileId)}.`,\n\t\t\tstack: e instanceof Error ? e.stack : undefined,\n\t\t});\n\t}\n\tconst fileExt = extname(fileId);\n\tconst entryConfig = entryConfigByExt.get(fileExt);\n\n\tif (!entryConfig) {\n\t\tthrow new AstroError({\n\t\t\t...AstroErrorData.UnknownContentCollectionError,\n\t\t\tmessage: `No parser found for data entry ${JSON.stringify(\n\t\t\t\tfileId,\n\t\t\t)}. Did you apply an integration for this file type?`,\n\t\t});\n\t}\n\tconst entry = pathToFileURL(fileId);\n\tconst collection = getEntryCollectionName({ entry, contentDir });","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/withastro/astro/blob/d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca/packages/astro/src/content/vite-plugin-content-imports.ts#L329-L365","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import { existsSync } from 'fs';\nfunction preCheckEntry(fileId: string) {\n  if (!existsSync(fileId)) {\n    throw new Error(`Content entry missing before build: ${fileId}`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await build();\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Unexpected error reading entry')) {\n    console.error('Stale Vite cache or deleted file:', e.message);\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["content-collections","filesystem","vite","race-condition"],"backgroundTag":null,"analyzedSha":"d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca","analyzedAt":"2026-08-12T13:37:29.035Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}