withastro/astro · error · AstroError
NoImageMetadata
NoImageMetadata
Error message
Could not process image metadata for `${url}`. What it means
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.
Source
Thrown at packages/astro/src/assets/utils/remoteProbe.ts:132
accumulatedChunks = tmp;
try {
// Attempt to determine the size with each new chunk
const dimensions = await imageMetadata(accumulatedChunks, url);
if (dimensions) {
await reader.cancel(); // stop stream as we have size now
return dimensions;
}
} catch {
// This catch block is specifically for `imageMetadata` errors
// which might occur if the accumulated data isn't yet sufficient.
}
}
}
throw new AstroError({
...AstroErrorData.NoImageMetadata,
message: AstroErrorData.NoImageMetadata.message(url),
});
}
View on GitHub (pinned to d081033d5f)
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.
Example fix
<!-- before -- URL serves an HTML error page with 200 -->
<Image src="https://cdn/missing.png" inferSize alt="…" />
<!-- after -- fix upstream, or supply dimensions -->
<Image src="https://cdn/real.png" width={800} height={600} alt="…" /> Defensive patterns
Strategy: validation
Validate before calling
async function probesAsImage(url: string) {
const r = await fetch(url);
if (!r.ok) return false;
const buf = new Uint8Array(await r.arrayBuffer());
return hasImageMagic(buf); // reuse magic-byte guard
} Type guard
function isImageContentType(ct: string | null): boolean {
return !!ct && /^image\/(png|jpeg|webp|gif|avif)$/i.test(ct);
} Prevention
- 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).
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- NoImageMetadata
- FailedToFetchRemoteImageDimensions
- RemoteImageNotAllowed
- CannotOptimizeSvg
- SVG file does not contain an <svg> element
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/9efaf256d1373c74.
Report an issue: GitHub.