siyuan-note/siyuan · error

svg contains multiple root elements

Error message

svg contains multiple root elements

What it means

After the root <svg> element has been closed (rootClosed), any further StartElement token triggers this error. Well-formed XML allows exactly one root element, so a second top-level element means the input is a document fragment, concatenated SVGs, or has stray content after the root. The sanitizer enforces single-root XML semantics to keep output a valid standalone SVG.

Source

Thrown at kernel/util/misc.go:373

			break
		}
		if err != nil {
			return "", fmt.Errorf("parse svg failed: %w", err)
		}
		tokenCount++
		if tokenCount > maxSVGTokens {
			return "", fmt.Errorf("svg contains too many tokens")
		}

		switch typed := token.(type) {
		case xml.StartElement:
			elementStack = append(elementStack, typed.Name)
			depth++
			if depth > maxSVGDepth {
				return "", fmt.Errorf("svg nesting depth exceeds %d", maxSVGDepth)
			}
			if rootClosed {
				return "", fmt.Errorf("svg contains multiple root elements")
			}
			if !rootSeen {
				if !strings.EqualFold(typed.Name.Local, "svg") {
					return "", fmt.Errorf("root element is not svg")
				}
				rootSeen = true
			}

			if skipDepth > 0 {
				skipDepth++
				continue
			}
			if _, unsafe := unsafeSVGElements[strings.ToLower(typed.Name.Local)]; unsafe {
				skipDepth = 1
				continue
			}

			typed.Name = preserveXMLName(typed.Name)

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Ensure the input contains exactly one root <svg> element — split multiple icons into separate files/calls
  2. Strip any content (text, comments-producing artifacts, extra elements) after the closing </svg>
  3. Fix the template/packaging step that concatenates SVG documents; wrap multiple icons in distinct sanitized calls
  4. If a sprite is needed, place icons as <symbol> children inside a single root <svg> instead of sibling roots

Example fix

// before
combined := svg1 + svg2 // two root elements
out, err := util.SanitizeSVG(combined)
// after
out1, err1 := util.SanitizeSVG(svg1)
out2, err2 := util.SanitizeSVG(svg2) // sanitize each document separately
Defensive patterns

Strategy: validation

Validate before calling

if strings.Count(strings.TrimSpace(svg), "</svg>") > 1 { return errors.New("multiple root elements; split into separate SVG documents") }

Try / catch

out, err := util.SanitizeSVG(svg)
if err != nil && strings.Contains(err.Error(), "multiple root elements") {
    // split the input on '</svg>' boundaries and sanitize each part
}

Prevention

When it happens

Trigger: Passing content to SanitizeSVG that contains two sibling top-level elements — e.g. '<svg>...</svg><svg>...</svg>', 'text after </svg>', an SVG pasted twice, or template concatenation of multiple icon files.

Common situations: Batch-exported icon sets concatenated into one file, copy/paste that grabbed two icons, HTML snippets where multiple inline SVGs were joined, or a build step appending trailing content after the closing tag.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/ababb5d3bc4dc006. Report an issue: GitHub.