{"record":{"id":"8695e8fdb82a9933","repo":"withastro/astro","slug":"astro-expected-an-svg-for-transform-src-b","errorCode":null,"errorMessage":"⚠️  Astro expected an SVG for \"${transform.src}\" but the source is ${bufferFormat}. Passing it through as ${bufferFormat} instead.","messagePattern":"⚠️  Astro expected an SVG for \"(.+?)\" but the source is (.+?)\\. Passing it through as (.+?) instead\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/astro/src/assets/services/sharp.ts","lineNumber":161,"sourceCode":"\tvalidateOptions: baseService.validateOptions,\n\tgetURL: baseService.getURL,\n\tparseURL: baseService.parseURL,\n\tgetHTMLAttributes: baseService.getHTMLAttributes,\n\tgetSrcSet: baseService.getSrcSet,\n\tgetRemoteSize: baseService.getRemoteSize,\n\tasync transform(inputBuffer, transformOptions, config) {\n\t\tif (!sharp) sharp = await loadSharp();\n\t\tconst transform: BaseServiceTransform = transformOptions as BaseServiceTransform;\n\t\tconst kernel = config.service.config.kernel;\n\n\t\tconst bufferFormat = detector(inputBuffer);\n\t\t// Resolve the output format from the buffer when validateOptions deferred (ambiguous remote URL hit SSR, manually formed URLs etc)\n\t\tconst outputFormat = transform.format ?? resolveDefaultOutputFormat(bufferFormat);\n\n\t\t// TODO: Sharp has some support for SVGs, we could probably support this once Sharp is the default and only service.\n\t\tif (outputFormat === 'svg') {\n\t\t\tif (bufferFormat && bufferFormat !== 'svg') {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`⚠️  Astro expected an SVG for \"${transform.src}\" but the source is ${bufferFormat}. Passing it through as ${bufferFormat} instead.`,\n\t\t\t\t);\n\t\t\t\treturn { data: inputBuffer, format: bufferFormat as ImageOutputFormat };\n\t\t\t}\n\t\t\treturn { data: inputBuffer, format: 'svg' };\n\t\t}\n\n\t\t// If we couldn't figure out the format, it's probably something weird we shouldn't try to process.\n\t\tif (!bufferFormat) {\n\t\t\tthrow new AstroError({\n\t\t\t\t...AstroErrorData.NoImageMetadata,\n\t\t\t\tmessage: AstroErrorData.NoImageMetadata.message(transform.src),\n\t\t\t});\n\t\t}\n\n\t\tif (bufferFormat === 'svg' && !config.dangerouslyProcessSVG) {\n\t\t\tthrow new AstroError({\n\t\t\t\t...AstroErrorData.UnsupportedImageFormat,","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/withastro/astro/blob/52e6c34790cc8ac4e69e6135ace06049867e5c4a/packages/astro/src/assets/services/sharp.ts#L143-L179","documentation":"Astro's Sharp image service cannot encode SVG, so when the resolved output format for a transform is 'svg' but byte-level format detection reports a different input format, it warns and returns the original buffer unchanged, relabeled with the detected format. The detector sniffs magic bytes, not the file extension, so this fires when the source is not actually an SVG despite its name or the requested format.","triggerScenarios":"Passing format=\"svg\" on <Image>/<Picture> or in getImage()/image() options while the source's real bytes are PNG/JPEG/WebP; or hitting the deferred-format path (ambiguous remote URL resolved during SSR) where resolveDefaultOutputFormat() returns 'svg' for a non-SVG buffer. Classic trigger: a file with an .svg extension that actually contains raster data.","commonSituations":"A PNG renamed to .svg without conversion; design tools exporting 'SVG' files that embed raster images; CDN/remote URLs serving WebP or JPEG bytes under an .svg URL; copy-pasted format=\"svg\" props from snippets.","solutions":["Convert the source file to a real vector SVG so its bytes match the .svg extension","Remove the format=\"svg\" prop and let Astro choose the output format (e.g. webp)","Rename the source to its true extension (.png/.jpg) and update imports/references","If serving the raster as-is is acceptable, no action needed: the image still passes through, just unoptimized under its real format"],"exampleFix":"// before: logo.svg actually contains PNG bytes\n<Image src={logo} format=\"svg\" alt=\"Logo\" />\n\n// after: let Astro optimize into a supported raster format\n<Image src={logo} format=\"webp\" alt=\"Logo\" />","handlingStrategy":"validation","validationCode":"// Before passing an .svg asset with format=\"svg\", verify the bytes are really SVG:\nimport { readFile } from 'node:fs/promises';\nfunction isSvgBuffer(buf: Uint8Array): boolean {\n  const head = new TextDecoder().decode(buf.slice(0, 256)).trimStart().toLowerCase();\n  return head.startsWith('<?xml') || head.startsWith('<svg');\n}\nconst bytes = await readFile('src/assets/logo.svg');\nif (!isSvgBuffer(bytes)) throw new Error('logo.svg contains raster data — convert it or drop format=\"svg\"');","typeGuard":"type SharpEncodableFormat = 'webp' | 'png' | 'jpeg' | 'avif' | 'gif';\nconst SHARP_ENCODABLE = new Set(['webp', 'png', 'jpeg', 'avif', 'gif']);\nfunction isSharpEncodable(f: string): f is SharpEncodableFormat {\n  return SHARP_ENCODABLE.has(f);\n}","tryCatchPattern":null,"preventionTips":["Never request format=\"svg\" from the optimizer — Sharp cannot encode SVG","Treat file extensions as metadata, not truth; sniff bytes when sources are untrusted","Add a CI check that every committed .svg starts with '<svg' or '<?xml'"],"tags":["astro","images","sharp","svg","format-mismatch","image-service"],"backgroundTag":"image-format-mismatch","analyzedSha":"52e6c34790cc8ac4e69e6135ace06049867e5c4a","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}