d2lang/d2 · error

unknown svg path command

Error message

unknown svg path command "%s"

What it means

getSVGPathString reconstructs a command substring for a tokenized SVG path; it only supports M, L, C, and S commands, and returns this error for any other command token encountered in pathData. It means the path uses an SVG command the splitter does not implement.

Solutions

  1. Preprocess the SVG to convert unsupported commands (A→C arc flattening, Q/T→C, H/V→L) before splitting
  2. Normalize the path with an SVG path normalizer library
  3. Regenerate the diagram with settings that emit only cubic/line commands
  4. Extend the switch in lib/svg/path.go to handle the missing command
  5. Check the raw d attribute to confirm which command triggered it

Example fix

// before: path d="M0 0 A5 5 0 0 1 10 10" → error
// after: convert arcs to cubics before splitting
d = normalizeSVGPath(d) // A commands flattened to C
first, second, err := svg.SplitPath(d)
Defensive patterns

Strategy: validation

Validate before calling

func hasOnlySupportedCmds(d string) bool {
    for _, tok := range strings.Fields(d) {
        if len(tok) == 1 && strings.Contains("AQTHVZ"+strings.ToLower("AQTHVZ"), tok) { return false }
    }
    return true
}

Type guard

func isUnsupportedCmdErr(err error) bool { return strings.HasPrefix(err.Error(), "unknown svg path command") }

Try / catch

first, second, err := svg.SplitPath(pathData)
if err != nil && isUnsupportedCmdErr(err) {
    pathData = strings.Fields(normalizeToCubics(strings.Join(pathData, " ")))
    first, second, err = svg.SplitPath(pathData)
}

Prevention

When it happens

Trigger: SplitPath (directly or via pathLength/getPathStringIncrement) on a path whose d attribute contains commands like A (arc), Q/T (quadratic), H/V, or Z, which have no case in the switch.

Common situations: Diagrams or exported SVGs produced by tools that emit arcs (A) for rounded shapes or quadratic curves (Q/T); hand-written SVG with H/V relative commands.

Related errors


AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31). Data as JSON: /api/errors/a486025aeecad3dc. Report an issue: GitHub.

Appendix: source

Thrown at lib/svg/path.go:161

		Y: (u1*u1*u1)*p1.Y + (3*t1*u1*u1)*p2.Y + (3*t1*t1*u1)*p3.Y + t1*t1*t1*p4.Y,
	}

	return q1, q2, q3, q4
}

// Gets a certain line/curve's SVG path string. offsetIdx and pathData provides the points needed
func getSVGPathString(pathType string, offsetIdx int, pathData []string) (string, error) {
	switch pathType {
	case "M":
		return fmt.Sprintf("M %s %s ", pathData[offsetIdx+1], pathData[offsetIdx+2]), nil
	case "L":
		return fmt.Sprintf("L %s %s ", pathData[offsetIdx+1], pathData[offsetIdx+2]), nil
	case "C":
		return fmt.Sprintf("C %s %s %s %s %s %s ", pathData[offsetIdx+1], pathData[offsetIdx+2], pathData[offsetIdx+3], pathData[offsetIdx+4], pathData[offsetIdx+5], pathData[offsetIdx+6]), nil
	case "S":
		return fmt.Sprintf("S %s %s %s %s ", pathData[offsetIdx+1], pathData[offsetIdx+2], pathData[offsetIdx+3], pathData[offsetIdx+4]), nil
	default:
		return "", fmt.Errorf("unknown svg path command \"%s\"", pathData[offsetIdx])
	}
}

// Gets how much to increment by on an SVG string to get to the next path command
func getPathStringIncrement(pathType string) (int, error) {
	switch pathType {
	case "M":
		return 3, nil
	case "L":
		return 3, nil
	case "C":
		return 7, nil
	case "S":
		return 5, nil
	default:
		return 0, fmt.Errorf("unknown svg path command \"%s\"", pathType)
	}
}

View on GitHub (pinned to 0d69dca6f5)