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
- 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.
- Ensure the file starts at byte 0 with '---' — remove any BOM or leading blank lines.
- 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
- Start every SKILL.md with a '---' frontmatter fence containing at least name:.
- Lint SKILL.md frontmatter in CI with a YAML parser before publishing.
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
- Skill manifest name '{manifestName}' does not match package
- Skill {name} version {version} already exists with a differe
- File path is required
- skillRef is required
- Skill manifest is required
AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14).
Data as JSON: /api/errors/633ad01b9c6c00ec.
Report an issue: GitHub.