d2lang/d2 · error

unknown svg path command "%s"

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.

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)

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.