sipeed/picoclaw · error
skill patch frontmatter name %q does not match target skill
Error message
skill patch frontmatter name %q does not match target skill %q
What it means
renderDeployablePatchBody (pkg/evolution/apply.go:228) strips frontmatter from append/merge patch bodies; if the patch carries a `name` it must equal the target skill or be omitted entirely. Unlike the full-body check (where name is required and must match), the patch name is optional but must not disagree — a disagreeing patch header means the patch was written for a different skill.
Source
Thrown at pkg/evolution/apply.go:228
}, "\n")
return strings.TrimRight(existingBody, "\n") + mergedSection, nil
default:
return "", fmt.Errorf("unsupported change_kind %q", draft.ChangeKind)
}
}
func renderDeployablePatchBody(body, targetSkillName string) (string, error) {
body = renderDeployableSkillBody(body)
frontmatter, markdownBody := splitSkillFrontmatter(body)
if frontmatter == "" {
markdownBody = body
} else {
fields, err := parseSkillFrontmatterFields(frontmatter, true)
if err != nil {
return "", err
}
if name := strings.TrimSpace(fields["name"]); name != "" && name != targetSkillName {
return "", fmt.Errorf(
"skill patch frontmatter name %q does not match target skill %q",
name,
targetSkillName,
)
}
}
return strings.TrimSpace(stripLeadingH1(markdownBody)), nil
}
func splitSkillFrontmatter(body string) (frontmatter, markdownBody string) {
normalized := strings.ReplaceAll(strings.TrimSpace(body), "\r\n", "\n")
lines := strings.Split(normalized, "\n")
if len(lines) == 0 || strings.TrimSpace(lines[0]) != "---" {
return "", body
}
end := -1
for i := 1; i < len(lines); i++ {
if strings.TrimSpace(lines[i]) == "---" {View on GitHub (pinned to 49183d7e8d)
Solutions
- Remove the `name:` key from the patch frontmatter (it is stripped during rendering anyway)
- Or set the patch frontmatter name to exactly draft.TargetSkillName
- Regenerate the patch without copying source-skill frontmatter
Example fix
// before (append patch) --- name: source-skill description: ... --- ## New section // after ## New section
Defensive patterns
Strategy: validation
Validate before calling
func patchNameAgrees(body, target string) error {
// reuse frontmatter extraction; only fail when a name is present AND different
var fm struct {
Name string `yaml:"name"`
}
if fmBlock := extractFrontmatter(body); fmBlock != "" {
if err := yaml.Unmarshal([]byte(fmBlock), &fm); err == nil {
if n := strings.TrimSpace(fm.Name); n != "" && n != target {
return fmt.Errorf("patch name %q != target %q", n, target)
}
}
return nil
} Try / catch
if err := applier.ApplyDraft(ctx, ws, draft); err != nil {
if strings.Contains(err.Error(), "skill patch frontmatter name") {
// drop or correct the name key in the patch frontmatter
}
} Prevention
- Author append/merge patches as bare markdown sections — no frontmatter at all
- When excerpting other skills, strip their frontmatter before reusing the text
- A patch frontmatter name is optional; when in doubt omit it
When it happens
Trigger: Append/merge draft whose BodyOrPatch frontmatter declares `name: other-skill` while TargetSkillName differs — typically a patch excerpted from another skill's SKILL.md with its frontmatter left in, or an LLM echoing the source skill's name into the patch header.
Common situations: Shortcut/merge drafts assembled by copying sections of existing skill files; copy-paste patch authoring; generator prompts that include example frontmatter from a differently-named skill.
Related errors
- skill frontmatter name %q does not match target skill %q
- skill frontmatter description is required
- skill frontmatter is required
- skill frontmatter name is required
- unsupported skill frontmatter field %q
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/4f2a88c226a9c07c.
Report an issue: GitHub.