{"record":{"id":"9f8c55dd09880438","repo":"withastro/astro","slug":"imagenotfound-9f8c55","errorCode":"ImageNotFound","errorMessage":"Could not find requested image `${imagePath}`. Does it exist?","messagePattern":"Could not find requested image `(.+?)`\\. Does it exist\\?","errorType":"error_code","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/content/vite-plugin-content-assets.ts","lineNumber":57,"sourceCode":"\t\tname: 'astro:content-asset-propagation',\n\t\tenforce: 'pre',\n\t\tresolveId: {\n\t\t\tfilter: {\n\t\t\t\tid: new RegExp(`(?:\\\\?|&)(?:${CONTENT_IMAGE_FLAG}|${CONTENT_RENDER_FLAG})(?:&|=|$)`),\n\t\t\t},\n\t\t\tasync handler(id, importer, opts) {\n\t\t\t\tif (hasContentFlag(id, CONTENT_IMAGE_FLAG)) {\n\t\t\t\t\tconst [base, query] = id.split('?');\n\t\t\t\t\tconst params = new URLSearchParams(query);\n\t\t\t\t\tconst importerParam = params.get('importer');\n\n\t\t\t\t\tconst importerPath = importerParam\n\t\t\t\t\t\t? fileURLToPath(new URL(importerParam, settings.config.root))\n\t\t\t\t\t\t: importer;\n\n\t\t\t\t\tconst resolved = await this.resolve(base, importerPath, { skipSelf: true, ...opts });\n\t\t\t\t\tif (!resolved) {\n\t\t\t\t\t\tthrow new AstroError({\n\t\t\t\t\t\t\t...AstroErrorData.ImageNotFound,\n\t\t\t\t\t\t\tmessage: AstroErrorData.ImageNotFound.message(base),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t// Preserve the content image flag in the resolved ID so that downstream plugins\n\t\t\t\t\t// (e.g. astro:assets:esm) can detect content collection images and avoid creating\n\t\t\t\t\t// full SVG components, which would import from the server runtime and cause a\n\t\t\t\t\t// circular module dependency deadlock when combined with top-level await (TLA).\n\t\t\t\t\tresolved.id = `${resolved.id}?${CONTENT_IMAGE_FLAG}`;\n\t\t\t\t\treturn resolved;\n\t\t\t\t}\n\t\t\t\tif (hasContentFlag(id, CONTENT_RENDER_FLAG)) {\n\t\t\t\t\tconst base = id.split('?')[0];\n\n\t\t\t\t\tfor (const { extensions, handlePropagation = true } of settings.contentEntryTypes) {\n\t\t\t\t\t\tif (handlePropagation && extensions.includes(extname(base))) {\n\t\t\t\t\t\t\treturn this.resolve(`${base}?${PROPAGATED_ASSET_FLAG}`, importer, {\n\t\t\t\t\t\t\t\tskipSelf: true,","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/withastro/astro/blob/d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca/packages/astro/src/content/vite-plugin-content-assets.ts#L39-L75","documentation":"Thrown by the content assets Vite plugin when a content collection image import cannot be resolved by Vite's module resolver. The plugin's `resolveId` hook intercepts IDs flagged with `CONTENT_IMAGE_FLAG`, strips the flag, and delegates to `this.resolve()`. If resolution returns null (file does not exist or path is wrong), the error is thrown with the base image path.","triggerScenarios":"A content entry (Markdown/MDX) references an image via a relative path or `@assets/` alias that does not resolve to an actual file. The `CONTENT_IMAGE_FLAG` query param triggers the handler, `this.resolve(base, importerPath)` returns null, and `ImageNotFound` is thrown.","commonSituations":"Typo in the image filename or extension. Image was deleted or not yet committed. Relative path is wrong relative to the entry file's location. Using an alias that isn't configured in `tsconfig.json` paths or Vite config. Case-sensitivity mismatch on Linux CI vs. macOS dev.","solutions":["Verify the image path in the error message exists on disk, exactly as spelled (case-sensitive).","Ensure the path is relative to the content entry file, not the project root.","If using an alias like `@assets/`, confirm it is mapped in `tsconfig.json` compilerOptions.paths.","Check `git status` to confirm the image is committed if the error occurs in CI.","Add the correct file extension (.png, .jpg, .webp, .svg)."],"exampleFix":"<!-- before -->\n![alt](../asets/logo.png)\n\n<!-- after -->\n![alt](../assets/logo.png)","handlingStrategy":"validation","validationCode":"import { existsSync } from 'fs';\nimport { resolve, dirname } from 'path';\nfunction imageExists(fromFilePath: string, imagePath: string): boolean {\n  const resolved = resolve(dirname(fromFilePath), imagePath);\n  return existsSync(resolved);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use absolute aliases (configured in tsconfig paths) for image imports to avoid relative path errors.","Commit images alongside content in the same PR.","Run CI on Linux to catch case-sensitivity issues before deployment."],"tags":["content-collections","images","vite","assets","path-resolution"],"backgroundTag":null,"analyzedSha":"d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca","analyzedAt":"2026-08-12T13:37:29.035Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}