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
- Read the appended `e.getMessage()` text — it names the YAML line/column of the failure; fix that line.
- Lint the frontmatter locally with `yamllint` or `yq` before packaging the skill.
- Confirm no tabs are used for indentation (YAML requires spaces).
- 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
- Lint every SKILL.md with `yamllint` before packaging.
- Never use tabs for indentation; configure the editor to insert spaces.
- Close all quotes and brackets; run `yq` locally as a smoke test.
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
- SKILL.md is missing required YAML frontmatter
- SKILL.md frontmatter must be a mapping
- Skill manifest name '{manifestName}' does not match package
- Skill {name} version {version} already exists with a differe
- File path is required
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/9622057f1ed09ae1.
Report an issue: GitHub.