conductor-oss/conductor · error · IllegalArgumentException

SKILL.md is missing required YAML frontmatter

Error message

SKILL.md is missing required YAML frontmatter

What it means

Thrown by parseSkillFrontmatter when SKILL.md does not begin with a YAML frontmatter block. The FRONTMATTER_PATTERN requires the file to start with '---' on its own line, then the YAML body, then a closing '---'. Without this block the skill name and parameters cannot be extracted, so parsing aborts before any field is read.

Source

Thrown at agentspan/src/main/java/org/conductoross/conductor/ai/agentspan/runtime/service/SkillRegistryService.java:567

            throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buffer = new byte[8192];
        long total = 0;
        int read;
        while ((read = in.read(buffer)) >= 0) {
            total += read;
            if (total > maxBytes) {
                throw new IllegalArgumentException(errorMessage);
            }
            out.write(buffer, 0, read);
        }
        return out.toByteArray();
    }

    private Map<String, Object> parseSkillFrontmatter(String skillMd) {
        Matcher matcher = FRONTMATTER_PATTERN.matcher(skillMd);
        if (!matcher.matches()) {
            throw new IllegalArgumentException("SKILL.md is missing required YAML frontmatter");
        }
        try {
            LoaderOptions options = new LoaderOptions();
            Yaml yaml = new Yaml(new SafeConstructor(options));
            Object value = yaml.load(matcher.group(1));
            if (value == null) {
                return Map.of();
            }
            if (!(value instanceof Map<?, ?> map)) {
                throw new IllegalArgumentException("SKILL.md frontmatter must be a mapping");
            }
            return MAPPER.convertValue(map, MAP_TYPE);
        } catch (IllegalArgumentException e) {
            throw e;
        } catch (Exception e) {
            throw new IllegalArgumentException(
                    "Invalid SKILL.md frontmatter: " + e.getMessage(), e);
        }

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Add a YAML frontmatter block at the very top of SKILL.md: a line with exactly '---', the YAML (at least name:), then a closing '---', then the body.
  2. Ensure the file starts at byte 0 with '---' — remove any BOM or leading blank lines.
  3. Validate the SKILL.md locally with a YAML frontmatter parser before zipping.

Example fix

---
name: my-skill
description: Does the thing.
---
# My Skill

Body text here.
Defensive patterns

Strategy: validation

Validate before calling

// Before zipping, verify SKILL.md has valid frontmatter
String md = Files.readString(skillMdPath);
if (!Pattern.compile("^---\\s*\\R.*?\\R---\\s*\\R?.*", Pattern.DOTALL).matcher(md).matches()) {
    throw new IllegalArgumentException("SKILL.md frontmatter missing");
}

Type guard

static boolean hasFrontmatter(String skillMd) {
    return skillMd != null && skillMd.startsWith("---") && skillMd.indexOf("---", 3) > 3;
}

Try / catch

try { skillRegistryService.register(manifest, pkg); }
catch (IllegalArgumentException e) {
    if (e.getMessage().contains("YAML frontmatter")) { /* add --- block to SKILL.md, re-zip */ }
    else throw e;
}

Prevention

When it happens

Trigger: POST /api/skills/register with a SKILL.md that starts with prose (e.g. '# My Skill') and has no leading '---' delimiters, or where the closing '---' is missing, or where leading whitespace/BOM precedes the first '---'.

Common situations: Authoring SKILL.md as plain markdown without frontmatter; a template that strips or misplaces the '---' fences; a UTF-8 BOM inserted by a Windows editor before the first '---'; an indented opening '---'.

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/633ad01b9c6c00ec. Report an issue: GitHub.