{"record":{"id":"a85fd7afcd8c3669","repo":"charmbracelet/crush","slug":"description-is-required","errorCode":null,"errorMessage":"description is required","messagePattern":"description is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/skills/skills.go","lineNumber":136,"sourceCode":"func (s *Skill) Validate() error {\n\tvar errs []error\n\n\tif s.Name == \"\" {\n\t\terrs = append(errs, errors.New(\"name is required\"))\n\t} else {\n\t\tif len(s.Name) > MaxNameLength {\n\t\t\terrs = append(errs, fmt.Errorf(\"name exceeds %d characters\", MaxNameLength))\n\t\t}\n\t\tif !namePattern.MatchString(s.Name) {\n\t\t\terrs = append(errs, errors.New(\"name must be alphanumeric with hyphens, no leading/trailing/consecutive hyphens\"))\n\t\t}\n\t\tif s.Path != \"\" && !strings.EqualFold(filepath.Base(s.Path), s.Name) {\n\t\t\terrs = append(errs, fmt.Errorf(\"name %q must match directory %q\", s.Name, filepath.Base(s.Path)))\n\t\t}\n\t}\n\n\tif s.Description == \"\" {\n\t\terrs = append(errs, errors.New(\"description is required\"))\n\t} else if len(s.Description) > MaxDescriptionLength {\n\t\terrs = append(errs, fmt.Errorf(\"description exceeds %d characters\", MaxDescriptionLength))\n\t}\n\n\tif len(s.Compatibility) > MaxCompatibilityLength {\n\t\terrs = append(errs, fmt.Errorf(\"compatibility exceeds %d characters\", MaxCompatibilityLength))\n\t}\n\n\treturn errors.Join(errs...)\n}\n\n// Parse parses a SKILL.md file from disk.\nfunc Parse(path string) (*Skill, error) {\n\tcontent, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/skills/skills.go#L118-L154","documentation":"Skill.Validate requires a non-empty Description; when present it must not exceed MaxDescriptionLength. An empty description means the frontmatter lacks `description:`, which the spec requires so the agent can decide when to use the skill.","triggerScenarios":"Parsing a SKILL.md without a `description:` key (or with an empty one) and calling Validate; also triggered indirectly when description exceeds MaxDescriptionLength (companion error).","commonSituations":"Minimal skill stubs created without frontmatter; templates copied with description removed; very long prose descriptions pasted in that blow the length cap.","solutions":["Add a concise `description:` line to the SKILL.md frontmatter","Shorten the description if it exceeds MaxDescriptionLength","Keep the description action-oriented (what the skill does and when to use it)"],"exampleFix":"// before\n---\nname: my-skill\n---\n// after\n---\nname: my-skill\ndescription: Reviews Go code for lint issues before commit\n---","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(skill.Description) == \"\" {\n\treturn errors.New(\"skill frontmatter must define a description\")\n}\nif len(skill.Description) > skills.MaxDescriptionLength {\n\treturn errors.New(\"description too long\")\n}","typeGuard":null,"tryCatchPattern":"if err := skill.Validate(); err != nil {\n\treturn fmt.Errorf(\"invalid skill description: %w\", err)\n}","preventionTips":["Always include a one-line description in frontmatter","Keep descriptions concise and under MaxDescriptionLength","Run validation on all skill files after editing"],"tags":["skills","validation","frontmatter"],"backgroundTag":"schema-validation-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}