siyuan-note/siyuan · error
svg nesting depth exceeds %d
Error message
svg nesting depth exceeds %d
What it means
SanitizeSVG tracks element nesting depth and rejects input once depth exceeds maxSVGDepth (256, kernel/util/misc.go:321). Deep nesting is a classic parser-stack-exhaustion / DoS vector, so the sanitizer caps it. Legitimate SVG icons nest only a handful of levels; exceeding 256 indicates pathological or malicious input.
Source
Thrown at kernel/util/misc.go:370
for {
token, err := decoder.RawToken()
if err == io.EOF {
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
continueView on GitHub (pinned to 8641553a1f)
Solutions
- Flatten the SVG structure (unwrap redundant <g> groups, run an SVG optimizer) before sanitizing
- Regenerate the asset from the original source instead of re-exporting repeatedly
- Treat the input as malicious if untrusted: reject it rather than raising the limit
- If a legitimate deep structure is required, raise maxSVGDepth deliberately with matching stack-safety review
Example fix
// before
svg := strings.Repeat("<g>", 1000) + content + strings.Repeat("</g>", 1000)
out, err := util.SanitizeSVG(svg) // fails at depth 257
// after
svg := flattenGroups(source) // unwrap nested <g> wrappers
out, err := util.SanitizeSVG(svg) Defensive patterns
Strategy: validation
Validate before calling
if strings.Count(svg, "<g")+strings.Count(svg, "<svg") > 200 { return errors.New("svg nesting too deep") } Try / catch
out, err := util.SanitizeSVG(svg)
if err != nil && strings.Contains(err.Error(), "nesting depth exceeds") {
// reject or flatten the SVG before retrying
} Prevention
- Flatten redundant <g> wrappers before import
- Avoid repeated export/import cycles that nest content further
- Treat deeply nested untrusted SVG as a DoS attempt and reject it
When it happens
Trigger: Calling SanitizeSVG with an SVG whose elements nest more than 256 levels deep — recursively generated SVG, a crafted <g><g><g>... bomb, or deeply nested XML produced by repeated wrapping during transformations.
Common situations: Algorithmically generated SVGs (fractals, recursion demos), icons passed through multiple export/import cycles that each wrapped content in extra groups, or malicious uploads targeting XML parser recursion.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- svg contains too many tokens
- parse svg failed: %w
- svg contains multiple root elements
- root element is not svg
- svg contains text outside the root element
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/e8a954569abcd8f0.
Report an issue: GitHub.