conductor-oss/conductor · error · IllegalArgumentException

Invalid SKILL.md frontmatter: {e.getMessage()}

Error message

Invalid SKILL.md frontmatter: {e.getMessage()}

What it means

Generic fallback thrown by the frontmatter parser when SnakeYAML itself (or the Jackson convertValue step) raises something other than IllegalArgumentException — typically a YAML scanner/parser error such as a bad indent, a stray tab, or an unterminated quote. The original exception's message is concatenated into the IllegalArgumentException so the author sees the underlying YAML problem.

Source

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

        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);
        }
    }

    private String decodeUtf8(String path, byte[] data) {
        try {
            return StandardCharsets.UTF_8
                    .newDecoder()
                    .onMalformedInput(CodingErrorAction.REPORT)
                    .onUnmappableCharacter(CodingErrorAction.REPORT)
                    .decode(ByteBuffer.wrap(data))
                    .toString();
        } catch (CharacterCodingException e) {
            throw new IllegalArgumentException("Skill file must be UTF-8 text: " + path, e);
        }
    }

    private boolean isRootAgentFile(String path) {

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Read the appended `e.getMessage()` text — it names the YAML line/column of the failure; fix that line.
  2. Lint the frontmatter locally with `yamllint` or `yq` before packaging the skill.
  3. Confirm no tabs are used for indentation (YAML requires spaces).
  4. If using anchors/aliases or custom tags, inline the values — SafeConstructor will not honor them.

Example fix

// before
---
name: my-skill
description: "unclosed quote
---
// after
---
name: my-skill
description: "properly closed quote"
---
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-validate the YAML before submitting to the registry.
private static void validateFrontmatterYaml(String skillMd) {
    Matcher m = FRONTMATTER_PATTERN.matcher(skillMd);
    if (!m.matches()) throw new IllegalArgumentException("missing frontmatter fences");
    try {
        new Yaml(new SafeConstructor(new LoaderOptions())).load(m.group(1));
    } catch (Exception e) {
        throw new IllegalArgumentException("frontmatter YAML invalid: " + e.getMessage(), e);
    }
}

Type guard

boolean isValidFrontmatterYaml(String skillMd) {
    Matcher m = FRONTMATTER_PATTERN.matcher(skillMd);
    if (!m.matches()) return false;
    try { new Yaml(new SafeConstructor(new LoaderOptions())).load(m.group(1)); return true; }
    catch (Exception e) { return false; }
}

Try / catch

try {
    skillRegistry.publish(skillMd);
} catch (IllegalArgumentException e) {
    // message already contains the underlying YAML error line/column
    return badRequest("SKILL.md frontmatter error: " + e.getMessage());
}

Prevention

When it happens

Trigger: SKILL.md frontmatter contains malformed YAML: tab indentation, unclosed quote, duplicate merge keys, or a tag SnakeYAML's SafeConstructor refuses (`!java/object:...`). The `catch (Exception e)` path wraps it.

Common situations: Editor inserts tabs; copy-paste from a markdown renderer that mangled spaces; author pasted a YAML anchor/alias SafeConstructor blocks; frontmatter ends mid-value due to a missing closing `---`.

Related errors


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