d2lang/d2 · error

expected "shadow" to be true or false

Error message

expected "shadow" to be true or false

What it means

D2's style-setting code (SetStyle style application in d2graph) parses the "shadow" style value with strconv.ParseBool. If the value cannot be parsed as a boolean, this error is returned instead of setting s.Shadow.Value. Only styles whose field is non-nil (i.e., marked as set) are validated.

Source

Thrown at d2graph/d2graph.go:383

			return errors.New(`expected "stroke-dash" to be a number between 0 and 10`)
		}
		s.StrokeDash.Value = value
	case "border-radius":
		if s.BorderRadius == nil {
			break
		}
		f, err := strconv.Atoi(value)
		if err != nil || (f < 0) {
			return errors.New(`expected "border-radius" to be a number greater or equal to 0`)
		}
		s.BorderRadius.Value = value
	case "shadow":
		if s.Shadow == nil {
			break
		}
		_, err := strconv.ParseBool(value)
		if err != nil {
			return errors.New(`expected "shadow" to be true or false`)
		}
		s.Shadow.Value = value
	case "3d":
		if s.ThreeDee == nil {
			break
		}
		_, err := strconv.ParseBool(value)
		if err != nil {
			return errors.New(`expected "3d" to be true or false`)
		}
		s.ThreeDee.Value = value
	case "multiple":
		if s.Multiple == nil {
			break
		}
		_, err := strconv.ParseBool(value)
		if err != nil {
			return errors.New(`expected "multiple" to be true or false`)

View on GitHub (pinned to 0d69dca6f5)

Solutions

  1. Change the shadow value to "true" or "false" (e.g. `x.shadow: true`).
  2. If using a numeric flag, use 1 for true or 0 for false.
  3. Remove the shadow key entirely if you only wanted the default (unset) behavior.
  4. If generating the value in code, ensure the string is produced by strconv.FormatBool or is one of the ParseBool-accepted literals.

Example fix

// before (D2)
x: my shape
x.shadow: yes
// after
x: my shape
x.shadow: true
Defensive patterns

Strategy: validation

Validate before calling

func validStyleBool(v string) bool {
	_, err := strconv.ParseBool(v)
	return err == nil
}
// before applying: if !validStyleBool(shadowVal) { /* fix or reject */ }

Type guard

func isParseBoolValue(s string) bool {
	switch s {
	case "1", "t", "T", "TRUE", "true", "True", "0", "f", "F", "FALSE", "false", "False":
		return true
	}
	return false
}

Try / catch

if err := obj.SetStyle("shadow", val); err != nil {
	if strings.Contains(err.Error(), `"shadow" to be true or false`) {
		// fall back to default or surface a friendly message
		val = "false"
	}
}

Prevention

When it happens

Trigger: Calling the style setter with style key "shadow" assigned a value other than strconv.ParseBool-accepted strings ("1", "t", "T", "TRUE", "true", "True", "0", "f", "F", "FALSE", "false", "False"), e.g. `x.shadow: yes` or `shadow: on` in a D2 diagram.

Common situations: Users writing D2 diagrams use natural-language truthy words like "yes", "no", "on", "off" or misspell "true"/"false"; also occurs when config is generated programmatically with Go boolean formatting variants not accepted by ParseBool.

Related errors


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