charmbracelet/crush · error
parsing frontmatter: %w
Error message
parsing frontmatter: %w
What it means
ParseContent splits a SKILL.md document into YAML frontmatter and a body, then unmarshals the frontmatter into a Skill struct. This error wraps any yaml.Unmarshal failure, meaning the frontmatter block is not valid YAML or does not match the Skill schema.
Source
Thrown at internal/skills/skills.go:175
return nil, err
}
skill.Path = filepath.Dir(path)
skill.SkillFilePath = path
return skill, nil
}
// ParseContent parses a SKILL.md from raw bytes.
func ParseContent(content []byte) (*Skill, error) {
frontmatter, body, err := splitFrontmatter(string(content))
if err != nil {
return nil, err
}
var skill Skill
if err := yaml.Unmarshal([]byte(frontmatter), &skill); err != nil {
return nil, fmt.Errorf("parsing frontmatter: %w", err)
}
skill.Instructions = strings.TrimSpace(body)
return &skill, nil
}
// splitFrontmatter extracts YAML frontmatter and body from markdown content.
func splitFrontmatter(content string) (frontmatter, body string, err error) {
// Strip UTF-8 BOM for compatibility with editors that include it.
content = strings.TrimPrefix(content, "\uFEFF")
// Normalize line endings to \n for consistent parsing.
content = strings.ReplaceAll(content, "\r\n", "\n")
content = strings.ReplaceAll(content, "\r", "\n")
lines := strings.Split(content, "\n")
start := slices.IndexFunc(lines, func(line string) bool {
return strings.TrimSpace(line) != ""View on GitHub (pinned to 7944b8e522)
Solutions
- Validate the YAML between the --- fences with a YAML linter/parser; fix indentation (spaces only, no tabs)
- Quote the `description:` and `compatibility:` values (or use block scalars | >) when they contain colons or special characters
- Ensure the file starts with `---`, has a closing `---`, and fields match the Skill schema (name, description, etc.)
Example fix
// before // description: Use when: user asks for tests // after // description: "Use when: user asks for tests"
Defensive patterns
Strategy: try-catch
Validate before calling
func hasFrontmatter(content string) bool {
lines := strings.SplitN(content, "\n", 2)
if len(lines) == 0 || strings.TrimSpace(lines[0]) != "---" {
return false
}
_, rest, ok := strings.Cut(content[4:], "\n---")
return ok && strings.TrimSpace(rest) != ""
} Try / catch
skill, err := skills.ParseContent(content)
if err != nil {
var skipped *fs.PathError
if errors.As(err, &skipped) {
return fmt.Errorf("unreadable skill file: %w", err)
}
return fmt.Errorf("invalid SKILL.md (check YAML frontmatter syntax, indentation, and --- fences): %w", err)
} Prevention
- Quote description/compatibility values containing colons or special YAML characters
- Use spaces, never tabs, for frontmatter indentation
- Verify the file begins with --- and has a matching closing --- fence
- Run SKILL.md files through a YAML linter in CI
When it happens
Trigger: Calling ParseContent (or Parse) on SKILL.md content whose frontmatter contains malformed YAML: bad indentation, tabs instead of spaces, unquoted special characters (e.g. colons in unquoted values), wrong types for fields, or missing/unclosed `---` delimiters (which can yield empty/invalid frontmatter).
Common situations: Hand-edited SKILL.md with YAML syntax mistakes; description containing unquoted colon-bearing text; copy-pasting frontmatter with tabs; editing with a tool that mangles the `---` fences; passing content with no frontmatter at all.
Related errors
- no YAML frontmatter found
- unclosed frontmatter
- name exceeds %d characters
- name is required
- description is required
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/2d2ad4a8498fba80.
Report an issue: GitHub.