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

  1. 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`.
  2. If the server returns HTML (error page), fix the upstream so it serves the real image with the right Content-Type.
  3. Re-encode the image to a well-supported raster format (PNG/JPEG/WebP).
  4. Provide explicit width/height and drop inferSize so Astro never needs to probe the bytes.
  5. 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

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


AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12). Data as JSON: /api/errors/9efaf256d1373c74. Report an issue: GitHub.