{"record":{"id":"2a58d2ce4944447b","repo":"d2lang/d2","slug":"no-color-stops-in-gradient","errorCode":null,"errorMessage":"no color stops in gradient","messagePattern":"no color stops in gradient","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/color/gradient.go","lineNumber":54,"sourceCode":"\tparams := matches[2]\n\n\tgradient := Gradient{\n\t\tType: strings.TrimSuffix(gradientType, \"-gradient\"),\n\t}\n\n\tparamList := splitParams(params)\n\n\tif len(paramList) == 0 {\n\t\treturn Gradient{}, errors.New(\"no parameters in gradient\")\n\t}\n\n\tfirstParam := strings.TrimSpace(paramList[0])\n\n\tif gradient.Type == \"linear\" && (strings.HasSuffix(firstParam, \"deg\") || strings.HasPrefix(firstParam, \"to \")) {\n\t\tgradient.Direction = firstParam\n\t\tcolorStops := paramList[1:]\n\t\tif len(colorStops) == 0 {\n\t\t\treturn Gradient{}, errors.New(\"no color stops in gradient\")\n\t\t}\n\t\tgradient.ColorStops = parseColorStops(colorStops)\n\t} else if gradient.Type == \"radial\" && (firstParam == \"circle\" || firstParam == \"ellipse\") {\n\t\tgradient.Direction = firstParam\n\t\tcolorStops := paramList[1:]\n\t\tif len(colorStops) == 0 {\n\t\t\treturn Gradient{}, errors.New(\"no color stops in gradient\")\n\t\t}\n\t\tgradient.ColorStops = parseColorStops(colorStops)\n\t} else {\n\t\tgradient.ColorStops = parseColorStops(paramList)\n\t}\n\tgradient.ID = UniqueGradientID(cssGradient)\n\n\treturn gradient, nil\n}\n\nfunc splitParams(params string) []string {","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/lib/color/gradient.go#L36-L72","documentation":"ParseGradient validates CSS gradient parameter lists. After a direction token (e.g. '45deg' or 'to right' for linear, 'circle'/'ellipse' for radial) is consumed, at least one color stop must remain; if the direction token is the only parameter, the gradient would have nothing to render, so it returns this error.","triggerScenarios":"Calling ParseGradient (indirectly via ValidColor) with a gradient string like 'linear-gradient(45deg)' or 'radial-gradient(circle)' where the parameter list contains only a direction and zero color stops.","commonSituations":"Hand-written CSS color values with a truncated gradient, templates interpolating an empty color list after a direction, or config files where the stops were accidentally dropped.","solutions":["Add at least one color stop after the direction, e.g. 'linear-gradient(45deg, #fff, #000)'","Remove the trailing direction-only parameter list or the whole gradient value if a plain color was intended","Validate the gradient string with ValidColor before use and surface a clearer message to the user"],"exampleFix":"// before\nParseGradient(\"linear-gradient(45deg)\")\n// after\nParseGradient(\"linear-gradient(45deg, blue, red)\")","handlingStrategy":"validation","validationCode":"params := strings.Split(inner, \",\")\nfirst := strings.TrimSpace(params[0])\nif (strings.HasSuffix(first, \"deg\") || strings.HasPrefix(first, \"to \")) && len(params) < 2 {\n    return errors.New(\"gradient needs at least one color stop after direction\")\n}","typeGuard":null,"tryCatchPattern":"g, err := ParseGradient(s)\nif err != nil {\n    // fallback: treat s as a plain color or surface the validation message\n}","preventionTips":["Always include at least one color stop after a direction token","Validate gradient strings with ValidColor before persisting them","Build gradients programmatically with strings.Join(stops, \", \") to avoid truncation"],"tags":["go","parsing","gradient","css"],"backgroundTag":"invalid-gradient-syntax","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}