sipeed/picoclaw · error

invalid skill frontmatter: %w

Error message

invalid skill frontmatter: %w

What it means

First pass of parseSkillFrontmatterFields (pkg/evolution/apply.go:260): yaml.Unmarshal of the text between the `---` markers into map[string]any failed, so the frontmatter block is not valid YAML mapping content. The underlying yaml.v3 error is wrapped with %w, preserving its line/column position.

Source

Thrown at pkg/evolution/apply.go:260

		return "", body
	}
	end := -1
	for i := 1; i < len(lines); i++ {
		if strings.TrimSpace(lines[i]) == "---" {
			end = i
			break
		}
	}
	if end < 0 {
		return "", body
	}
	return strings.Join(lines[1:end], "\n"), strings.TrimLeft(strings.Join(lines[end+1:], "\n"), "\n")
}

func parseSkillFrontmatterFields(frontmatter string, allowExtraFields bool) (map[string]string, error) {
	var raw map[string]any
	if err := yaml.Unmarshal([]byte(frontmatter), &raw); err != nil {
		return nil, fmt.Errorf("invalid skill frontmatter: %w", err)
	}
	for key := range raw {
		if key != "name" && key != "description" {
			if allowExtraFields {
				continue
			}
			return nil, fmt.Errorf("unsupported skill frontmatter field %q", key)
		}
	}

	var typed struct {
		Name        string `yaml:"name"`
		Description string `yaml:"description"`
	}
	if err := yaml.Unmarshal([]byte(frontmatter), &typed); err != nil {
		return nil, fmt.Errorf("invalid skill frontmatter: %w", err)
	}
	return map[string]string{

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Read the wrapped yaml.v3 error position and fix that line (quote values containing colons, replace tabs with spaces)
  2. Reduce frontmatter to plain `name:` and `description:` scalar lines
  3. Run yaml.Unmarshal on the extracted block yourself before applying to catch it early

Example fix

# before
---
name: deploy-checks
description: checks: run before deploy   # invalid second colon
---

# after
---
name: deploy-checks
description: "checks: run before deploy"
---
Defensive patterns

Strategy: validation

Validate before calling

func frontmatterParses(body string) error {
	block := extractFrontmatter(body) // text between the --- markers
	if block == "" {
		return nil
	}
	var raw map[string]any
	if err := yaml.Unmarshal([]byte(block), &raw); err != nil {
		return fmt.Errorf("frontmatter YAML invalid: %w", err)
	}
	return nil
}

Try / catch

if err := applier.ApplyDraft(ctx, ws, draft); err != nil {
	var yerr *yaml.TypeError
	if strings.Contains(err.Error(), "invalid skill frontmatter") || errors.As(err, &yerr) {
		// re-render or hand-fix the draft YAML at the reported line
	}
}

Prevention

When it happens

Trigger: Frontmatter with tab indentation, unterminated quotes, `key: value: value`, a stray `---` or colon structure inside a value, a plain scalar or list instead of `key: value` lines, or markdown prose accidentally inside the block — typically LLM-generated draft bodies where markdown bleeds above the body.

Common situations: LLM output malformed under token limits; hand-edited SKILL.md frontmatter; text pasted from terminals introducing tabs; description values containing unquoted colons followed by more text.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/dff3b2507cb0c825. Report an issue: GitHub.