siyuan-note/siyuan · error

svg contains text outside the root element

Error message

svg contains text outside the root element

What it means

Non-whitespace character data was found either before the root element opened or after it closed. Valid standalone SVG allows text only inside the <svg> root; stray text around it (or between multiple documents) is rejected both because it is not a valid SVG image and as an anti-smuggling measure.

Source

Thrown at kernel/util/misc.go:426

				if depth == 0 {
					rootClosed = true
				}
				continue
			}
			typed.Name = preserveXMLName(typed.Name)
			if err = encoder.EncodeToken(typed); err != nil {
				return "", fmt.Errorf("render svg failed: %w", err)
			}
			depth--
			if depth == 0 {
				rootClosed = true
			}
		case xml.CharData:
			if skipDepth > 0 {
				continue
			}
			if (!rootSeen || rootClosed) && strings.TrimSpace(string(typed)) != "" {
				return "", fmt.Errorf("svg contains text outside the root element")
			}
			if rootSeen && !rootClosed {
				if err = encoder.EncodeToken(typed); err != nil {
					return "", fmt.Errorf("render svg failed: %w", err)
				}
			}
		case xml.Comment:
			if skipDepth == 0 && rootSeen && !rootClosed {
				if err = encoder.EncodeToken(typed); err != nil {
					return "", fmt.Errorf("render svg failed: %w", err)
				}
			}
		case xml.Directive:
			if !isBenignSVGDoctype(string(typed)) {
				return "", fmt.Errorf("svg directives are not allowed")
			}
			// 良性 DOCTYPE 声明不写入输出,与 XML 声明(ProcInst)的处理方式一致,不影响浏览器渲染
		case xml.ProcInst:

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Delete the non-whitespace text outside the <svg>...</svg> range before sanitizing
  2. Extract just the svg element (regex or string slicing on the first '<svg' and last '</svg>') when accepting arbitrary pastes
  3. Do not concatenate multiple SVG documents; use <svg> with multiple children or an <symbol>/<use> structure instead
  4. Trim input and check that it starts with '<svg' or an allowed prolog (xml decl, comment, DOCTYPE)

Example fix

// before
SanitizeSVG("icon: <svg>...</svg>") // text outside the root element
// after
SanitizeSVG("<svg xmlns=\"http://www.w3.org/2000/svg\">...</svg>")
Defensive patterns

Strategy: validation

Validate before calling

func extractSVGDoc(input string) (string, bool) {
	start := strings.Index(input, "<svg")
	end := strings.LastIndex(input, "</svg>")
	if start < 0 || end < 0 || end <= start { return "", false }
	return input[start : end+len("</svg>")], true
}

Try / catch

doc, ok := extractSVGDoc(userInput)
if !ok { return errors.New("no complete svg element found in input") }
clean, err := util.SanitizeSVG(doc)
if err != nil { return err }

Prevention

When it happens

Trigger: 'hello<svg>...</svg>' (text before root), '<svg>...</svg>trailing text', two SVGs concatenated back to back with text in between, or an HTML wrapper with visible text around the svg tag.

Common situations: Pasting an SVG copied from a webpage along with surrounding text; concatenating icon files; log/console text accidentally included in the paste.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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