{"record":{"id":"b0783400e64047ab","repo":"GraphiteEditor/Graphite","slug":"error-reading-svg-file","errorCode":null,"errorMessage":"Error reading SVG file","messagePattern":"Error reading SVG file","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/utility-functions/rasterization.ts","lineNumber":69,"sourceCode":"\treturn blob;\n}\n\n/// Convert an image source (e.g. PNG document) into pixel data, a width, and a height\nexport async function extractPixelData(imageData: ImageBitmapSource): Promise<ImageData> {\n\tconst canvasContext = await imageToCanvasContext(imageData);\n\tconst width = canvasContext.canvas.width;\n\tconst height = canvasContext.canvas.height;\n\n\treturn canvasContext.getImageData(0, 0, width, height);\n}\n\nexport async function imageToCanvasContext(imageData: ImageBitmapSource): Promise<CanvasRenderingContext2D> {\n\t// Special handling to rasterize an SVG file\n\tlet svgImageData;\n\tif (imageData instanceof File && imageData.type === \"image/svg+xml\") {\n\t\tconst svgSource = await imageData.text();\n\t\tconst svgElement = new DOMParser().parseFromString(svgSource, \"image/svg+xml\").querySelector(\"svg\");\n\t\tif (!svgElement) throw new Error(\"Error reading SVG file\");\n\n\t\tlet bounds = svgElement.viewBox.baseVal;\n\n\t\t// If the bounds are zero (which will happen if the `viewBox` is not provided), set bounds to the artwork's bounding box\n\t\tif (bounds.width === 0 || bounds.height === 0) {\n\t\t\t// It's necessary to measure while the element is in the DOM, otherwise the dimensions are zero\n\t\t\tconst toRemove = document.body.insertAdjacentElement(\"beforeend\", svgElement);\n\t\t\tbounds = svgElement.getBBox();\n\t\t\ttoRemove?.remove();\n\t\t}\n\n\t\tsvgImageData = await rasterizeSVGCanvas(svgSource, bounds.width, bounds.height);\n\t}\n\n\t// Decode the image file binary data\n\tconst image = await createImageBitmap(svgImageData || imageData);\n\n\tlet { width, height } = image;","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/frontend/src/utility-functions/rasterization.ts#L51-L87","documentation":"imageToCanvasContext special-cases files with MIME image/svg+xml: it parses the text via DOMParser and queries for an <svg> root. If querySelector(\"svg\") finds nothing — a parsererror document, a non-SVG root, or a namespace-prefixed root like <svg:svg> that the tag-name selector does not match — it throws this generic error before rasterization begins.","triggerScenarios":"A File whose type is reported as image/svg+xml but whose content is not a valid SVG document: XML syntax errors (yielding a <parsererror> document), an HTML file saved with an .svg extension, a root element other than svg, or a namespace-prefixed <svg:svg> root.","commonSituations":"Users renaming arbitrary files to .svg; exports from tools that emit unusual XML (BOM, processing instructions) where the root is not a literal <svg> tag; import dialogs that trust extension-based MIME sniffing.","solutions":["Open the file in a text editor and confirm it is well-formed XML whose root element is <svg xmlns=\"http://www.w3.org/2000/svg\">","Re-export the artwork as a standard SVG from the source tool","If you control the code, check doc.querySelector(\"parsererror\") first and match the documentElement by namespace/localName instead of querySelector(\"svg\")","As a workaround, convert the SVG to PNG before importing"],"exampleFix":"// before\nconst svgElement = new DOMParser().parseFromString(svgSource, \"image/svg+xml\").querySelector(\"svg\");\nif (!svgElement) throw new Error(\"Error reading SVG file\");\n\n// after: distinguish parse errors from a wrong root, and match namespaces properly\nconst doc = new DOMParser().parseFromString(svgSource, \"image/svg+xml\");\nconst parseError = doc.querySelector(\"parsererror\");\nif (parseError) throw new Error(`Malformed SVG: ${parseError.textContent}`);\nconst svgElement = doc.documentElement?.localName === \"svg\" ? doc.documentElement : null;\nif (!svgElement) throw new Error(\"Error reading SVG file\");","handlingStrategy":"validation","validationCode":"function parseSvg(text: string): SVGSVGElement | null {\n\tconst doc = new DOMParser().parseFromString(text, \"image/svg+xml\");\n\tif (doc.querySelector(\"parsererror\")) return null;\n\tconst root = doc.documentElement;\n\treturn root?.namespaceURI === \"http://www.w3.org/2000/svg\" && root.localName === \"svg\"\n\t\t? (root as unknown as SVGSVGElement)\n\t\t: null;\n}","typeGuard":null,"tryCatchPattern":"// Wrap import call sites and surface the offending filename\ntry {\n\tconst ctx = await imageToCanvasContext(file);\n} catch (err) {\n\tshowImportError(file.name, err instanceof Error ? err.message : String(err));\n}","preventionTips":["Validate SVG files at the import dialog before rasterization","Prefer namespace-aware lookup (documentElement.localName/namespaceURI) over tag-name selectors","Check for a parsererror element before assuming the parsed root is usable"],"tags":["svg","file-import","rasterization","domparser"],"backgroundTag":"invalid-svg-file","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}