{"record":{"id":"2036212c84a2cc1d","repo":"withastro/astro","slug":"imagenotfound","errorCode":"ImageNotFound","errorMessage":"Could not find requested image `${id}`. Does it exist?","messagePattern":"Could not find requested image `(.+?)`\\. Does it exist\\?","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/assets/vite-plugin-assets.ts","lineNumber":364,"sourceCode":"\t\t\t\t\tif (id !== removeQueryString(id)) {\n\t\t\t\t\t\t// If our import has any query params, we'll let Vite handle it, nonetheless we'll make sure to not delete it\n\t\t\t\t\t\t// See https://github.com/withastro/astro/issues/8333\n\t\t\t\t\t\tglobalThis.astroAsset.referencedImages.add(removeQueryString(id));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// If the requested ID doesn't end with a valid image extension, we'll let Vite handle it\n\t\t\t\t\tif (!assetRegexEnds.test(id)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst fileEmitter = shouldEmitFile\n\t\t\t\t\t\t? (opts: Parameters<typeof this.emitFile>[0]) => emitClientAsset(this as any, opts)\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tconst imageMetadata = await emitImageMetadata(id, fileEmitter);\n\n\t\t\t\t\tif (!imageMetadata) {\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(id),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t// We can only reliably determine if an image is used on the server, as we need to track its usage throughout the entire build.\n\t\t\t\t\t// Since you cannot use image optimization on the client anyway, it's safe to assume that if the user imported\n\t\t\t\t\t// an image on the client, it should be present in the final build.\n\t\t\t\t\tif (isAstroServerEnvironment(this.environment)) {\n\t\t\t\t\t\t// For SVGs imported directly (not via content collections), create a full\n\t\t\t\t\t\t// component that can be rendered inline. For content collection SVGs, the\n\t\t\t\t\t\t// component is reconstructed later in content/runtime.ts from __svgData\n\t\t\t\t\t\t// embedded in the metadata, avoiding a server-runtime import here that\n\t\t\t\t\t\t// would create a circular dependency when combined with TLA.\n\t\t\t\t\t\tif (id.endsWith('.svg')) {\n\t\t\t\t\t\t\tconst contents = await fs.promises.readFile(imageMetadata.fsPath, {\n\t\t\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t\t\t});","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/withastro/astro/blob/d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca/packages/astro/src/assets/vite-plugin-assets.ts#L346-L382","documentation":"In the vite-plugin-assets load hook, after the import id passes the image-extension regex, Astro calls emitImageMetadata(id). If that returns undefined (the asset could not be resolved to a file or its metadata could not be produced), it throws ImageNotFound. This is the ESM-import path: `import x from './x.png'` where the file does not exist or is unreadable.","triggerScenarios":"ESM-importing an image asset whose path does not resolve to an existing file (typo, wrong relative path, case-sensitivity mismatch on Linux, missing file), or whose metadata could not be emitted. The regex check already passed, so the extension was valid but the file is absent.","commonSituations":"Relative import path typo (`./img.png` vs `../img.png`); case-sensitive filename mismatch on a case-sensitive FS after committing on macOS/Windows; file deleted or renamed without updating imports; Markdown image path not starting with `./`; path computed dynamically and resolving wrong.","solutions":["Check the import path character-by-character and verify the file exists with `ls`.","On case-sensitive filesystems, match the exact filename casing.","In Markdown, prefix same-folder images with `./` (per the error hint).","If the file was moved, update the import or run a repo-wide find-and-replace.","Confirm the asset is actually committed (not gitignored) when building in CI."],"exampleFix":"// before\nimport hero from './Hero.png'; // actual file: hero.png (lowercase)\n\n// after\nimport hero from './hero.png';","handlingStrategy":"validation","validationCode":"import { existsSync, statSync } from 'node:fs';\nimport { resolve } from 'node:path';\nfunction assetExists(p: string): boolean {\n  const full = resolve(p);\n  return existsSync(full) && statSync(full).isFile();\n}","typeGuard":"function isRelativeAsset(p: string): boolean {\n  return /^\\.\\.?\\//.test(p) && /\\.(png|jpe?g|webp|avif|gif|svg)$/i.test(p);\n}","tryCatchPattern":null,"preventionTips":["Use exact casing on case-sensitive filesystems.","In Markdown, prefix same-folder images with ./.","Ensure assets are committed to git (not gitignored) for CI builds."],"tags":["assets","import","file-not-found","validation"],"backgroundTag":null,"analyzedSha":"d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca","analyzedAt":"2026-08-12T13:37:29.035Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}