{"record":{"id":"6645f87dff0c9726","repo":"withastro/astro","slug":"cannotoptimizesvg","errorCode":"CannotOptimizeSvg","errorMessage":"An error occurred while optimizing SVG file \"${path}\" with the \"${svgOptimizer.name}\" optimizer.","messagePattern":"An error occurred while optimizing SVG file \"(.+?)\" with the \"(.+?)\" optimizer\\.","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/assets/svg/utils.ts","lineNumber":22,"sourceCode":"import { dropAttributes } from '../runtime.js';\nimport type { ImageMetadata } from '../types.js';\nimport type { SvgOptimizer } from './types.js';\n\nasync function parseSvg({\n\tpath,\n\tcontents,\n\tsvgOptimizer,\n}: {\n\tpath: string;\n\tcontents: string;\n\tsvgOptimizer: SvgOptimizer | undefined;\n}) {\n\tlet processedContents = contents;\n\tif (svgOptimizer) {\n\t\ttry {\n\t\t\tprocessedContents = await svgOptimizer.optimize(contents);\n\t\t} catch (cause) {\n\t\t\tthrow new AstroError(\n\t\t\t\t{\n\t\t\t\t\t...AstroErrorData.CannotOptimizeSvg,\n\t\t\t\t\tmessage: AstroErrorData.CannotOptimizeSvg.message(path, svgOptimizer.name),\n\t\t\t\t},\n\t\t\t\t{ cause },\n\t\t\t);\n\t\t}\n\t}\n\tconst root = parse(processedContents);\n\tconst svgNode = root.children.find(\n\t\t({ name, type }: { name: string; type: number }) => type === ELEMENT_NODE && name === 'svg',\n\t);\n\tif (!svgNode) {\n\t\tthrow new Error('SVG file does not contain an <svg> element');\n\t}\n\tconst { attributes, children } = svgNode;\n\tconst body = renderSync({ ...root, children });\n","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/withastro/astro/blob/d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca/packages/astro/src/assets/svg/utils.ts#L4-L40","documentation":"Astro throws this when a configured SVG optimizer's optimize() function rejects while processing an imported SVG asset. The SVG pipeline (experimental.svgOptimizer, e.g. svgo) is invoked on the file contents before parsing, and any rejection from its optimize() is wrapped as an AstroError carrying the original error as cause. The message names the file path and the optimizer's `name` field so you can tell which optimizer failed.","triggerScenarios":"Calling ESM-import of an .svg asset while experimental.svgOptimizer is set, where the optimizer's optimize(contents) throws (invalid SVG syntax, unsupported node, bad optimizer config, or a transformer bug). Triggered via assets pipeline -> svg/utils.ts optimizeSvg() when svgOptimizer is defined.","commonSituations":"Pointing experimental.svgOptimizer at svgo with a custom pluginConfig that chokes on a particular SVG; an SVG containing elements/attributes the optimizer cannot handle; an author-supplied custom SvgOptimizer whose optimize() throws on edge inputs; version mismatch between svgo and a hand-written plugin.","solutions":["Inspect the `cause` on the AstroError in your stack trace — it carries the optimizer's original error and is the real reason.","Run the same SVG through the optimizer directly (e.g. `svgo input.svg`) outside Astro to reproduce and isolate the bad input.","Fix or re-export the offending SVG from your editor (remove unsupported elements/attributes the optimizer flagged).","If the optimizer config is wrong, correct experimental.svgOptimizer in astro.config.mjs (or the options you pass to svgoOptimizer()).","Temporarily unset experimental.svgOptimizer to confirm the SVG itself is otherwise valid, then reintroduce the optimizer."],"exampleFix":"// before\nimport svgo from './broken.svg'; // optimizer throws on this file\n\n// after — sanitize the SVG, or pass tolerant svgo config\nimport { svgoOptimizer } from 'astro/assets/svg/svgo';\nexport default defineConfig({\n  experimental: { svgOptimizer: svgoOptimizer({ floatPrecision: 1, multipass: true }) },\n});","handlingStrategy":"try-catch","validationCode":"// Validate SVG is well-formed and has an <svg> root before importing through the optimizer\nimport { readFileSync } from 'node:fs';\nfunction looksLikeSvg(path: string) {\n  const txt = readFileSync(path, 'utf8');\n  return /<svg[\\s>]/i.test(txt) && txt.trim().endsWith('</svg>');\n}\n// skip optimizer when false","typeGuard":"import type { SvgOptimizer } from 'astro/assets';\nfunction isSvgOptimizer(v: unknown): v is SvgOptimizer {\n  return typeof v === 'object' && v !== null\n    && typeof (v as SvgOptimizer).name === 'string'\n    && typeof (v as SvgOptimizer).optimize === 'function';\n}","tryCatchPattern":"try {\n  // import/optimization happens inside Astro's pipeline; catch at the build boundary\n  await astroBuild();\n} catch (e) {\n  if (e instanceof Error && /CannotOptimizeSvg/.test(e.message)) {\n    console.error('SVG optimizer failed for', e.message, '\\ncause:', e.cause);\n  } else throw e;\n}","preventionTips":["Run new SVGs through your optimizer standalone before committing them.","Pin your svgo/optimizer version and lock its config.","Keep experimental.svgOptimizer disabled in CI unless you intentionally test optimization."],"tags":["svg","assets","optimization","configuration"],"backgroundTag":null,"analyzedSha":"d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca","analyzedAt":"2026-08-12T13:37:29.035Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}