withastro/astro · error · AstroError

UnsupportedImageFormat

UnsupportedImageFormat

Error message

SVG image processing is disabled, but the source for "${transform.src}" is an SVG. Pass it through unchanged by setting `format="svg"` on the component, or set `image.dangerouslyProcessSVG: true` to rasterize SVG sources.

What it means

For safety, Astro refuses to feed SVG sources through the rasterizing Sharp pipeline unless you explicitly opt in. When the probed input format is 'svg', the requested output is raster, and `image.dangerouslyProcessSVG` is falsy, the sharp service throws UnsupportedImageFormat with instructions: pass SVGs through unchanged, or set the flag to rasterize them.

Solutions

  1. Keep the SVG vectorial: set `format="svg"` on the component so it passes through unchanged
  2. Enable rasterization explicitly in astro.config.mjs: `image: { dangerouslyProcessSVG: true }` when you accept the security trade-off
  3. Pre-convert the SVG to PNG/WebP offline (e.g. with sharp CLI or an export tool) and ship the raster asset instead

Example fix

// before
<Image src={logo} alt="Logo" />

// after (pass-through)
<Image src={logo} format="svg" alt="Logo" />
Defensive patterns

Strategy: validation

Validate before calling

// before rendering, decide pass-through vs rasterize explicitly
const wantsRaster = targetFormat !== 'svg';
const sourceIsSvg = (typeof src !== 'string' && src.format === 'svg') || String(src).endsWith('.svg');
if (sourceIsSvg && wantsRaster && !astroConfig.image.dangerouslyProcessSVG) {
  // choose one: pass through, or enable the flag
  targetFormat = 'svg';
}

Type guard

function needsSvgPassthrough(srcFormat: string, requested: string | undefined, flagOn: boolean): boolean {
  return srcFormat === 'svg' && requested !== 'svg' && !flagOn;
}

Try / catch

try {
  const img = await getImage({ src, format });
} catch (err) {
  if (err instanceof AstroError && err.code === 'UnsupportedImageFormat') {
    return getImage({ src, format: 'svg' }); // pass through unchanged
  }
  throw err;
}

Prevention

When it happens

Trigger: `<Image src={logoSvg} />` (default webp output) without `dangerouslyProcessSVG`; `getImage({ src: svgImport, format: 'png' })`; a remote .svg URL used with the Image component requesting raster output.

Common situations: Using a logo.svg like any other image; upgrading Astro to a version that made SVG processing opt-in; processing user-supplied SVGs (XSS risk if rasterization re-embeds scripts); CI builds that differ from local because config drifted.

Related errors


AI-assisted analysis of withastro/astro@e294953aa8 (2026-08-18). Data as JSON: /api/errors/8ebb7c01722e6180. Report an issue: GitHub.

Appendix: source

Thrown at packages/astro/src/assets/services/sharp.ts:178

			if (bufferFormat && bufferFormat !== 'svg') {
				logger.warn(
					`Astro expected an SVG for "${transform.src}" but the source is ${bufferFormat}. Passing it through as ${bufferFormat} instead.`,
				);
				return { data: inputBuffer, format: bufferFormat as ImageOutputFormat };
			}
			return { data: inputBuffer, format: 'svg' };
		}

		// If we couldn't figure out the format, it's probably something weird we shouldn't try to process.
		if (!bufferFormat) {
			throw new AstroError({
				...AstroErrorData.NoImageMetadata,
				message: AstroErrorData.NoImageMetadata.message(transform.src),
			});
		}

		if (bufferFormat === 'svg' && !config.dangerouslyProcessSVG) {
			throw new AstroError({
				...AstroErrorData.UnsupportedImageFormat,
				message: `SVG image processing is disabled, but the source for "${transform.src}" is an SVG. Pass it through unchanged by setting \`format="svg"\` on the component, or set \`image.dangerouslyProcessSVG: true\` to rasterize SVG sources.`,
			});
		}

		const result = sharp(inputBuffer, {
			failOn: 'none',
			pages: -1,
			limitInputPixels: config.service.config.limitInputPixels,
		});

		// always call rotate to adjust for EXIF data orientation
		result.rotate();

		if (transform.width && transform.height) {
			const fit: keyof FitEnum | undefined = transform.fit
				? (fitMap[transform.fit] ?? 'inside')
				: undefined;

View on GitHub (pinned to e294953aa8)