withastro/astro · error · Error
Vercel Image Optimization requires at least one size to be…
Error message
Vercel Image Optimization requires at least one size to be configured.
What it means
The Vercel adapter's image service maps every transform to one of the configured sizes (the widths Vercel Image Optimization may serve). In development, sharedValidateOptions requires a non-empty sizes list: with images: true the adapter supplies defaults ([640...3840]), but a custom imagesConfig with sizes: [] or no sizes key makes dev throw.
Solutions
- Provide at least one width: imagesConfig: { sizes: [640, 750, 1080, 1920] }
- Omit imagesConfig entirely to use the adapter defaults ([640, 750, 828, 1080, 1200, 1920, 2048, 3840])
- If you set the service config via astro.config image.service.config, make sure it carries the same non-empty sizes
Example fix
// before
vercel({ images: true, imagesConfig: { sizes: [], domains: ['cdn.example.com'] } })
// after
vercel({ images: true, imagesConfig: { sizes: [640, 750, 1080, 1920], domains: ['cdn.example.com'] } }) Defensive patterns
Strategy: validation
Validate before calling
const DEFAULT_SIZES = [640, 750, 828, 1080, 1200, 1920, 2048, 3840];
const imagesConfig = {
sizes: DEFAULT_SIZES,
...userImagesConfig,
};
if (!imagesConfig.sizes?.length) throw new Error('imagesConfig.sizes must not be empty'); Type guard
function hasNonEmptySizes(config: unknown): config is { sizes: [number, ...number[]] } {
return Array.isArray((config as any)?.sizes) && (config as any).sizes.length > 0;
} Prevention
- Omit imagesConfig to inherit the adapter's default sizes
- Validate adapter config in a preflight script run before astro dev
- Re-check the sizes key whenever you copy a VercelImageConfig example
When it happens
Trigger: Configuring vercel({ images: true, imagesConfig: { sizes: [] } }) or an imagesConfig object lacking sizes, then rendering any Image/getImage in astro dev; production does not hit this check.
Common situations: Copying a minimal VercelImageConfig that only sets domains/remotePatterns and forgets sizes; disabling sizes intentionally on Vercel's dashboard config and mirroring that locally; stale examples from older adapter versions.
Related errors
- maxDuration must be a number
- Your "vercel.json" config is not a valid json file.
- Apps must be an object with an id, a name and an entrypoint.
- [astro] deprecated. Move onto your processor instead (e.g…
- `Astro.session` was accessed but no session storage is…
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/84f47040f1116059.
Report an issue: GitHub.
Appendix: 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 52e6c34790)