sipeed/picoclaw · error
skill frontmatter name is required
Error message
skill frontmatter name is required
What it means
After splitting and parsing the frontmatter, validateAppliedSkillBody requires a non-empty trimmed value for the `name` field. The error means `name` is absent, null, empty, or whitespace-only in the frontmatter block. (A follow-on check, not this error, enforces that name matches the target skill.)
Source
Thrown at pkg/evolution/apply.go:161
return strings.Contains(strings.ToLower(err.Error()), "directory not empty")
}
func validateAppliedSkillBody(body, targetSkillName string, allowExtraFrontmatterFields bool) error {
body = strings.TrimSpace(body)
if !strings.HasPrefix(body, "---\n") {
return fmt.Errorf("skill frontmatter is required")
}
if !strings.Contains(body, "\n# ") {
return fmt.Errorf("skill heading is required")
}
frontmatter, _ := splitSkillFrontmatter(body)
fields, err := parseSkillFrontmatterFields(frontmatter, allowExtraFrontmatterFields)
if err != nil {
return err
}
name := strings.TrimSpace(fields["name"])
if name == "" {
return fmt.Errorf("skill frontmatter name is required")
}
if name != targetSkillName {
return fmt.Errorf("skill frontmatter name %q does not match target skill %q", name, targetSkillName)
}
if strings.TrimSpace(fields["description"]) == "" {
return fmt.Errorf("skill frontmatter description is required")
}
return nil
}
func allowsExistingFrontmatterFields(kind ChangeKind, hadOriginal bool) bool {
return hadOriginal && (kind == ChangeKindAppend || kind == ChangeKindMerge)
}
func renderAppliedBody(draft SkillDraft, existingBody string, hadOriginal bool) (string, error) {
switch draft.ChangeKind {
case ChangeKindCreate:
if hadOriginal {View on GitHub (pinned to 49183d7e8d)
Solutions
- Add `name: <exact target skill name>` as a top-level (column-0) frontmatter key
- If the value contains special YAML characters, quote it: name: "my-skill:v2"
- Check the key spelling and that it is not indented (must sit at column 0 within the block)
- Validate locally by parsing the frontmatter and asserting a non-blank name before applying
Example fix
# before --- description: Deploys the app --- # Deploy ... # after --- name: deploy description: Deploys the app --- # Deploy ...
Defensive patterns
Strategy: validation
Validate before calling
func frontmatterNamePresent(body string) bool {
b := strings.TrimSpace(body)
if !strings.HasPrefix(b, "---\n") {
return false
}
rest := strings.TrimPrefix(b, "---\n")
end := strings.Index(rest, "\n---")
if end < 0 {
return false
}
for _, line := range strings.Split(rest[:end], "\n") {
if v, ok := strings.CutPrefix(line, "name:"); ok {
return strings.TrimSpace(v) != ""
}
}
return false
} Try / catch
if err := apply.Change(body); err != nil {
if strings.Contains(err.Error(), "skill frontmatter name is required") {
return fmt.Errorf("add 'name: <target-skill>' to the frontmatter block: %w", err)
}
return err
} Prevention
- Include 'name:' at column 0 in every frontmatter block, matching the target skill name
- Quote values containing colons or special YAML characters
- Lint generated frontmatter (name and description non-empty) before submitting evolution changes
When it happens
Trigger: Applying a skill whose frontmatter has only description (---\ndescription: x\n---); `name:` with no value or `name: ""`; name written with a tab indent so the field parser does not recognize the key; name key misspelled (Name:, title:) so fields["name"] is never set.
Common situations: Hand-written frontmatter omitting name because the filename seems sufficient; YAML copied from another tool using a different key; indentation errors from mixing tabs and spaces; LLM-generated frontmatter dropping fields.
Related errors
- skill frontmatter is required
- skill frontmatter name %q does not match target skill %q
- skill frontmatter description is required
- skill heading is required
- skill patch frontmatter name %q does not match target skill
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/2fd02ed80b667b23.
Report an issue: GitHub.