withastro/astro · error · Error

Vercel Image Optimization requires at least one size to be c

Error message

Vercel Image Optimization requires at least one size to be configured.

What it means

Thrown by the Vercel image service's `sharedValidateOptions` when, in development mode, the configured `image.service.config.sizes` array is empty or absent. Vercel Image Optimization serves only a discrete set of widths, so at least one must be declared.

Source

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

			},
		};
	}

	return {};
}

export function sharedValidateOptions(
	options: ImageTransform,
	serviceConfig: Record<string, any>,
	mode: 'development' | 'production',
) {
	const vercelImageOptions = serviceConfig as VercelImageConfig;

	if (
		mode === 'development' &&
		(!vercelImageOptions.sizes || vercelImageOptions.sizes.length === 0)
	) {
		throw new Error('Vercel Image Optimization requires at least one size to be configured.');
	}

	const configuredWidths = vercelImageOptions.sizes.sort((a, b) => a - b);

	// The logic for finding the perfect width is a bit confusing, here it goes:
	// For images where no width has been specified:
	// - For local, imported images, fall back to nearest width we can find in our configured
	// - For remote images, that's an error, width is always required.
	// 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)) {

View on GitHub (pinned to d081033d5f)

Solutions

  1. Add `sizes` to the image service config: `image: { service: { entrypoint: '@astrojs/vercel/image-service', config: { sizes: [320, 640, 1024] } } }`.
  2. Provide at least one width even for local dev; Vercel requires an explicit discrete set.
  3. Verify the config is nested under `service.config`, not directly under `image`.

Example fix

// before
export default defineConfig({
  image: { service: { entrypoint: '@astrojs/vercel/image-service' } },
});
// after
export default defineConfig({
  image: {
    service: {
      entrypoint: '@astrojs/vercel/image-service',
      config: { sizes: [320, 640, 1024, 1920] },
    },
  },
});
Defensive patterns

Strategy: validation

Validate before calling

const sizes = serviceConfig?.sizes;
if (mode === 'development' && (!Array.isArray(sizes) || sizes.length === 0)) {
  throw new Error('Configure image.service.config.sizes with at least one width.');
}

Type guard

function hasValidSizes(cfg: unknown): cfg is { sizes: number[] } {
  return Array.isArray((cfg as any)?.sizes) && (cfg as any).sizes.length > 0;
}

Prevention

When it happens

Trigger: Configuring `image: { service: { entrypoint: '@astrojs/vercel/image-service' } }` without a `config: { sizes: [...] }`. Setting `sizes: []`. Running in `dev` (the guard is `mode === 'development'`).

Common situations: Following a tutorial that omits the sizes config. Copying a production-only config into a dev environment. Expecting a default sizes list that does not exist.

Related errors


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