{"record":{"id":"9efaf256d1373c74","repo":"withastro/astro","slug":"noimagemetadata-9efaf2","errorCode":"NoImageMetadata","errorMessage":"Could not process image metadata for `${url}`.","messagePattern":"Could not process image metadata for `(.+?)`\\.","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/assets/utils/remoteProbe.ts","lineNumber":132,"sourceCode":"\t\t\taccumulatedChunks = tmp;\n\n\t\t\ttry {\n\t\t\t\t// Attempt to determine the size with each new chunk\n\t\t\t\tconst dimensions = await imageMetadata(accumulatedChunks, url);\n\n\t\t\t\tif (dimensions) {\n\t\t\t\t\tawait reader.cancel(); // stop stream as we have size now\n\n\t\t\t\t\treturn dimensions;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// This catch block is specifically for `imageMetadata` errors\n\t\t\t\t// which might occur if the accumulated data isn't yet sufficient.\n\t\t\t}\n\t\t}\n\t}\n\n\tthrow new AstroError({\n\t\t...AstroErrorData.NoImageMetadata,\n\t\tmessage: AstroErrorData.NoImageMetadata.message(url),\n\t});\n}\n","sourceCodeStart":114,"sourceCodeEnd":137,"githubUrl":"https://github.com/withastro/astro/blob/d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca/packages/astro/src/assets/utils/remoteProbe.ts#L114-L137","documentation":"End of inferRemoteSize(): the entire response body was streamed and accumulated, but imageMetadata() never returned dimensions on any chunk (each attempt was caught and swallowed). Astro gives up and throws NoImageMetadata for the URL — meaning the remote bytes were fetched fully but are not parseable as a known image.","triggerScenarios":"A remote URL that serves non-image bytes (HTML 200 error page, a PDF, a video poster), a truncated stream that closes before the dimension header, or an image format the vendored probe cannot recognise. Distinct from error 49: response WAS ok and had a body, but the bytes are unparseable.","commonSituations":"200 OK HTML error page from a misconfigured CDN instead of the image; SVG served as a remote image (probe may not extract raster dims); HEIC/odd format on an older Astro; partial read because the server closed keep-alive early; CORS/proxy injecting content.","solutions":["Download the URL with curl and run `file` on the result to confirm it is actually an image: `curl -L <url> -o x && file x`.","If the server returns HTML (error page), fix the upstream so it serves the real image with the right Content-Type.","Re-encode the image to a well-supported raster format (PNG/JPEG/WebP).","Provide explicit width/height and drop inferSize so Astro never needs to probe the bytes.","If the format is unsupported by probe, vendor the asset locally."],"exampleFix":"<!-- before -- URL serves an HTML error page with 200 -->\n<Image src=\"https://cdn/missing.png\" inferSize alt=\"…\" />\n\n<!-- after -- fix upstream, or supply dimensions -->\n<Image src=\"https://cdn/real.png\" width={800} height={600} alt=\"…\" />","handlingStrategy":"validation","validationCode":"async function probesAsImage(url: string) {\n  const r = await fetch(url);\n  if (!r.ok) return false;\n  const buf = new Uint8Array(await r.arrayBuffer());\n  return hasImageMagic(buf); // reuse magic-byte guard\n}","typeGuard":"function isImageContentType(ct: string | null): boolean {\n  return !!ct && /^image\\/(png|jpeg|webp|gif|avif)$/i.test(ct);\n}","tryCatchPattern":null,"preventionTips":["Serve images with correct Content-Type from your CDN.","Return proper non-200 statuses for missing images instead of HTML 200 pages.","Avoid passing remote SVGs through inferSize (use raster formats)."],"tags":["assets","remote-images","image-metadata","corruption"],"backgroundTag":null,"analyzedSha":"d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca","analyzedAt":"2026-08-12T13:37:29.035Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}