{"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":400,"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":382,"sourceCodeEnd":418,"githubUrl":"https://github.com/withastro/astro/blob/e294953aa8aadd98d5be92e60a03037b05dbdfd4/packages/astro/src/assets/vite-plugin-assets.ts#L382-L418","documentation":"During build, Astro's assets plugin resolves imported images and calls `emitImageMetadata(id)` to read their dimensions. If that returns nothing — almost always because the file does not exist on disk — the plugin throws ImageNotFound ('Could not find requested image `${id}`') instead of letting Vite produce a confusing resolution error further down.","triggerScenarios":"`import hero from '../images/hero.png'` where the file was deleted, renamed, or the relative path is wrong; casing mismatch on case-sensitive CI filesystems (Hero.png vs hero.png) that works locally on macOS/Windows; imports generated from content collections referencing removed files.","commonSituations":"Renaming assets in a PR while another branch still imports old names; git not tracking empty directories or lfs-filtered files after fresh clones; Windows-local works but Linux CI fails on path case; scaffolding templates referencing optional images.","solutions":["Check the exact `id` in the error message against the filesystem: does the file exist at that path with that exact casing","Fix the import path or restore/rename the file so they match (mind case sensitivity for CI on Linux)","If the import is generated (content collections, glob), regenerate the references or make the generator skip missing files"],"exampleFix":"// before\nimport hero from '../images/Hero.png'; // file is hero.png\n\n// after\nimport hero from '../images/hero.png';","handlingStrategy":"validation","validationCode":"// verify every imported image exists before build (case-sensitive!)\nimport { existsSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\n\nfunction assertImportExists(importer: string, spec: string): void {\n  if (spec.startsWith('.')) {\n    const target = join(dirname(importer), spec);\n    if (!existsSync(target)) {\n      throw new Error(`Missing image: ${spec} imported from ${importer}`);\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  const meta = await emitImageMetadata(id);\n  if (!meta) throw Object.assign(new Error(`Image not found: ${id}`), { code: 'ImageNotFound' });\n} catch (err) {\n  if ((err as { code?: string }).code === 'ImageNotFound') {\n    // fail fast with the exact path so CI output is actionable\n    process.exitCode = 1;\n  }\n  throw err;\n}","preventionTips":["Develop with case-sensitive path checking (Linux CI or a lint rule) to catch Hero.png vs hero.png","Codemod imports when renaming asset files instead of hand-editing"],"tags":["astro","images","import","file-not-found","path-casing","ci"],"backgroundTag":"image-import-not-found","analyzedSha":"e294953aa8aadd98d5be92e60a03037b05dbdfd4","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}