withastro/astro · error · Error

Missing `width` parameter for remote image ${options.src}

Error message

Missing `width` parameter for remote image ${options.src}

What it means

Thrown by the Vercel image service when a remote (non-imported) image has no `width` set. Vercel cannot infer dimensions for remote URLs, and unlike local imported images it cannot fall back to the nearest configured size from source metadata.

Source

Thrown at packages/integrations/vercel/src/image/shared.ts:139

	// For images where a width has been specified:
	// - If the width that the user asked for isn't in `sizes`, then fall back to the nearest one, but save the width
	// 	the user asked for so we can put it on the `img` tag later.
	// - Otherwise, just use as-is.
	// The end goal is:
	// - The size on the page is always the one that the user asked for or the base image's size
	// - The actual size of the image file is always one of `sizes`, either the one that the user asked for or the nearest to it
	if (!options.width) {
		const src = options.src;
		if (isESMImportedImage(src)) {
			const nearestWidth = configuredWidths.reduce((prev, curr) => {
				return Math.abs(curr - src.width) < Math.abs(prev - src.width) ? curr : prev;
			});

			// Use the image's base width to inform the `width` and `height` on the `img` tag
			options.inputtedWidth = src.width;
			options.width = nearestWidth;
		} else {
			throw new Error(`Missing \`width\` parameter for remote image ${options.src}`);
		}
	} else {
		if (!configuredWidths.includes(options.width)) {
			const nearestWidth = configuredWidths.reduce((prev, curr) => {
				return Math.abs(curr - options.width!) < Math.abs(prev - options.width!) ? curr : prev;
			});

			// Save the user's requested width to inform the `width` and `height` on the `img` tag
			options.inputtedWidth = options.width;
			options.width = nearestWidth;
		}
	}

	if (options.widths) {
		// Vercel only supports a fixed set of widths, so remove any that aren't in the list
		options.widths = options.widths.filter((w) => configuredWidths.includes(w));
		// Oh no, we've removed all the widths! Let's add the nearest one back in
		if (options.widths.length === 0) {

View on GitHub (pinned to d081033d5f)

Solutions

  1. Add an explicit `width` (and ideally `height`) to the `<Image>`/`getImage` call for any remote `src`.
  2. Import local images as ESM (`import photo from './photo.png'`) so dimensions are inferred automatically.
  3. If the remote source is actually yours, download and import it instead of referencing by URL.

Example fix

// before
<Image src="https://cdn.example.com/hero.jpg" alt="hero" />
// after
<Image src="https://cdn.example.com/hero.jpg" alt="hero" width={1920} height={1080} />
Defensive patterns

Strategy: validation

Validate before calling

function needsWidth(src: unknown): boolean {
  return typeof src === 'string'; // remote URLs are strings; imports are objects
}
if (needsWidth(options.src) && !options.width) {
  throw new Error('Remote images require an explicit width.');
}

Type guard

function isRemoteSrc(src: unknown): src is string {
  return typeof src === 'string';
}

Prevention

When it happens

Trigger: Using `<Image src="https://example.com/photo.jpg" />` (string URL) without `width`. Passing a remote URL to `getImage()` without a `width` transform. The `options.src` is not an ESM-imported image object, so the `isESMImportedImage` branch is skipped.

Common situations: Treating remote images like local imports (which auto-supply width/height). Migrating from another adapter that defaulted dimensions. Forgetting `width` on dynamic remote URLs.

Related errors


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