{"record":{"id":"6e06a4c56d530144","repo":"withastro/astro","slug":"could-not-resolve-image-json-stringify-node-attr","errorCode":null,"errorMessage":"Could not resolve image ${JSON.stringify(node.attributes.src)} from ${JSON.stringify(ctx.filePath)}. Does the file exist?","messagePattern":"Could not resolve image (.+?) from (.+?)\\. Does the file exist\\?","errorType":"exception","errorClass":"MarkdocError","httpStatus":null,"severity":"error","filePath":"packages/integrations/markdoc/src/content-entry-type.ts","lineNumber":337,"sourceCode":"\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: (opts: Parameters<typeof ctx.pluginContext.emitFile>[0]) =>\n\t\t\t\t\t\t\t\temitClientAsset(ctx.pluginContext, opts);\n\t\t\t\t\tconst src = await emitImageMetadata(resolved.id, fileEmitter);\n\n\t\t\t\t\tconst fsPath = resolved.id;\n\n\t\t\t\t\tif (src) {\n\t\t\t\t\t\t// We cannot track images in Markdoc, Markdoc rendering always strips out the proxy. As such, we'll always\n\t\t\t\t\t\t// assume that the image is referenced elsewhere, to be on safer side.\n\t\t\t\t\t\tif (ctx.astroConfig.output === 'static') {\n\t\t\t\t\t\t\tif (globalThis.astroAsset.referencedImages)\n\t\t\t\t\t\t\t\tglobalThis.astroAsset.referencedImages.add(fsPath);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tnode.attributes[attributeName] = { ...src, fsPath };\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthrow new MarkdocError({\n\t\t\t\t\t\tmessage: `Could not resolve image ${JSON.stringify(\n\t\t\t\t\t\t\tnode.attributes.src,\n\t\t\t\t\t\t)} from ${JSON.stringify(ctx.filePath)}. Does the file exist?`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (isComponent) {\n\t\t\t\t// If the user is using the {% image %} tag, always pass the `src` attribute as `__optimizedSrc`, even if it's an external URL or absolute path.\n\t\t\t\t// That way, the component can decide whether or not to optimize it.\n\t\t\t\tnode.attributes[attributeName] = node.attributes.src;\n\t\t\t}\n\t\t}\n\t\tawait emitOptimizedImages(node.children, ctx);\n\t}\n}\n\nfunction shouldOptimizeImage(src: string) {\n\t// Optimize anything that is NOT external or an absolute path to `public/`\n\treturn !isValidUrl(src) && !src.startsWith('/');","sourceCodeStart":319,"sourceCodeEnd":355,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/integrations/markdoc/src/content-entry-type.ts#L319-L355","documentation":"While transforming Markdoc content, the integration tries to resolve each image node's `src` through Astro's asset pipeline (emitting optimized images). If `src` cannot be resolved to a local file, it throws this MarkdocError echoing the raw src and the containing file path. Only resolvable local images and handled component forms make it through; an unresolvable path aborts the build.","triggerScenarios":"An image node / `{% image %}` tag in a .mdoc file whose `src` points to a nonexistent local file — wrong relative path, moved asset, missing extension — while not matching the component/remote-URL escape hatches.","commonSituations":"Content authors referencing images from a different directory depth; assets moved during refactors; case-sensitivity mismatches on case-sensitive filesystems/CI.","solutions":["Check that the path in the error exists, relative to the content file shown in the message.","Fix the relative prefix (`./`, `../`) or move the image into the referenced location.","For remote images, use the full URL form supported by the {% image %} component path rather than a bare path.","Watch for case mismatches between the filename in content and on disk."],"exampleFix":"{% image src=\"../images/hero.png\" alt=\"Hero\" /%}\n\n{% image src=\"./images/hero.png\" alt=\"Hero\" /%}","handlingStrategy":"validation","validationCode":"// Verify image sources referenced by .mdoc files exist before build\nimport { Markdoc } from '@markdoc/markdoc';\nimport { globSync } from 'glob';\nimport fs from 'node:fs';\nimport path from 'node:path';\nfor (const f of globSync('src/**/*.mdoc')) {\n  for (const node of Markdoc.parse(fs.readFileSync(f, 'utf8')).walk()) {\n    if (node.type !== 'image' && node.tag !== 'image') continue;\n    const src = node.attributes?.src;\n    if (typeof src === 'string' && !/^(https?:)?\\/\\//.test(src)) {\n      if (!fs.existsSync(path.resolve(path.dirname(f), src))) {\n        throw new Error(`${f}: image not found: ${src}`);\n      }\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store content-adjacent images at a fixed relative depth and document the convention.","Add an asset-existence lint to CI (also catches case mismatches on Linux runners).","Use remote URLs or the {% image %} component path for images outside the content tree."],"tags":["markdoc","images","asset-resolution","content","build"],"backgroundTag":"asset-resolution-failed","analyzedSha":"52e6c34790cc8ac4e69e6135ace06049867e5c4a","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}