{"record":{"id":"9c3c132fea052903","repo":"sipeed/picoclaw","slug":"skill-frontmatter-description-is-required","errorCode":null,"errorMessage":"skill frontmatter description is required","messagePattern":"skill frontmatter description is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/evolution/apply.go","lineNumber":167,"sourceCode":"\t\treturn fmt.Errorf(\"skill frontmatter is required\")\n\t}\n\tif !strings.Contains(body, \"\\n# \") {\n\t\treturn fmt.Errorf(\"skill heading is required\")\n\t}\n\tfrontmatter, _ := splitSkillFrontmatter(body)\n\tfields, err := parseSkillFrontmatterFields(frontmatter, allowExtraFrontmatterFields)\n\tif err != nil {\n\t\treturn err\n\t}\n\tname := strings.TrimSpace(fields[\"name\"])\n\tif name == \"\" {\n\t\treturn fmt.Errorf(\"skill frontmatter name is required\")\n\t}\n\tif name != targetSkillName {\n\t\treturn fmt.Errorf(\"skill frontmatter name %q does not match target skill %q\", name, targetSkillName)\n\t}\n\tif strings.TrimSpace(fields[\"description\"]) == \"\" {\n\t\treturn fmt.Errorf(\"skill frontmatter description is required\")\n\t}\n\treturn nil\n}\n\nfunc allowsExistingFrontmatterFields(kind ChangeKind, hadOriginal bool) bool {\n\treturn hadOriginal && (kind == ChangeKindAppend || kind == ChangeKindMerge)\n}\n\nfunc renderAppliedBody(draft SkillDraft, existingBody string, hadOriginal bool) (string, error) {\n\tswitch draft.ChangeKind {\n\tcase ChangeKindCreate:\n\t\tif hadOriginal {\n\t\t\treturn \"\", fmt.Errorf(\"cannot create skill %q: skill already exists\", draft.TargetSkillName)\n\t\t}\n\t\treturn renderDeployableSkillBody(draft.BodyOrPatch), nil\n\tcase ChangeKindReplace:\n\t\tif !hadOriginal {\n\t\t\treturn \"\", fmt.Errorf(\"cannot replace skill %q: skill does not exist\", draft.TargetSkillName)","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/evolution/apply.go#L149-L185","documentation":"Final check of validateAppliedSkillBody (pkg/evolution/apply.go:167): the rendered skill body's frontmatter must contain a non-empty `description`. renderDeployableSkillBody already substitutes a default string when a `description:` line exists with an empty value, so in practice this fires when the description key is missing entirely — either from a create/replace draft body, or from the preserved frontmatter of an existing skill being appended/merged onto.","triggerScenarios":"Create/replace draft whose BodyOrPatch frontmatter contains only `name:`; append/merge onto an existing SKILL.md whose frontmatter never had a `description:` key; hand-edited draft JSON that dropped the field.","commonSituations":"LLM omitting description despite the generator prompt requiring it (skillDraftPromptInstructions); legacy skills written before description became mandatory; hand-trimmed SKILL.md files.","solutions":["Add a non-empty `description:` line to the draft body's frontmatter","For append/merge, add a description to the existing target SKILL.md frontmatter first","Regenerate the draft with the description requirement enforced"],"exampleFix":"// before\n---\nname: deploy-checks\n---\n# Deploy checks\n\n// after\n---\nname: deploy-checks\ndescription: Run pre-deploy checks and report failures\n---\n# Deploy checks","handlingStrategy":"validation","validationCode":"func frontmatterHasDescription(body string) error {\n\tlines := strings.Split(strings.TrimSpace(body), \"\\n\")\n\tif len(lines) < 2 || strings.TrimSpace(lines[0]) != \"---\" {\n\t\treturn nil\n\t}\n\tfor i := 1; i < len(lines); i++ {\n\t\tif strings.TrimSpace(lines[i]) == \"---\" {\n\t\t\tbreak\n\t\t}\n\t\tif strings.HasPrefix(strings.TrimSpace(lines[i]), \"description:\") {\n\t\t\tif strings.TrimSpace(strings.TrimPrefix(strings.TrimSpace(lines[i]), \"description:\")) != \"\" {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t}\n\treturn fmt.Errorf(\"frontmatter description key missing or empty\")\n}","typeGuard":null,"tryCatchPattern":"if err := applier.ApplyDraft(ctx, ws, draft); err != nil {\n\tif strings.Contains(err.Error(), \"description is required\") {\n\t\t// add description to draft body (or to the existing target SKILL.md for append/merge)\n\t}\n}","preventionTips":["Always author draft frontmatter with both name and description; note a `description:` line with empty value gets a default substituted, but a missing key fails","For append/merge, check the existing target SKILL.md has a description before applying","Include description presence in your draft review/scan step before apply"],"tags":["go","skills","frontmatter","yaml","validation"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}