{"record":{"id":"379e4a00b9c555f5","repo":"zeroclaw-labs/zeroclaw","slug":"skill-content-is-missing-yaml-front-matter-expect","errorCode":null,"errorMessage":"Skill content is missing YAML front-matter (expected `---` delimited block at top)","messagePattern":"Skill content is missing YAML front-matter \\(expected `---` delimited block at top\\)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/skills/improver.rs","lineNumber":140,"sourceCode":"        self.cooldowns.insert(slug.to_string(), Instant::now());\n\n        Ok(Some(slug.to_string()))\n    }\n\n    fn skills_dir(&self) -> PathBuf {\n        self.workspace_dir.join(\"skills\")\n    }\n}\n\n/// Validate skill content: must be non-empty, have a parseable YAML front-matter\n/// block with a non-empty `name` field.\npub fn validate_skill_content(content: &str) -> Result<()> {\n    if content.trim().is_empty() {\n        bail!(\"Skill content is empty\");\n    }\n\n    let Some((front, _body)) = split_front_matter(content) else {\n        bail!(\"Skill content is missing YAML front-matter (expected `---` delimited block at top)\");\n    };\n\n    let name = front_matter_value(&front, \"name\").unwrap_or_default();\n    if name.trim().is_empty() {\n        bail!(\"Skill front-matter missing required `name` field\");\n    }\n\n    Ok(())\n}\n\n/// Split a SKILL.md into (front_matter_text, body_text).\n/// Returns `None` if the file doesn't start with `---\\n` or has no closing\n/// `---` delimiter.\nfn split_front_matter(content: &str) -> Option<(String, String)> {\n    let normalized = content.replace(\"\\r\\n\", \"\\n\");\n    let rest = normalized.strip_prefix(\"---\\n\")?;\n    if let Some(idx) = rest.find(\"\\n---\\n\") {\n        Some((rest[..idx].to_string(), rest[idx + 5..].to_string()))","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/skills/improver.rs#L122-L158","documentation":"validate_skill_content splits SKILL.md on a --- delimited YAML front-matter block via split_front_matter, which requires the file to start with a literal '---\\n' (after CRLF normalization) and to contain a closing '---' on its own line. This error means no such block was found, so there is nowhere to read the required name field from.","triggerScenarios":"Passing markdown body with no front-matter; front-matter not at byte 0 (leading blank line, comment, or UTF-8 BOM); missing closing '---'; an opening '---' immediately followed by text on the same line instead of a newline.","commonSituations":"LLM-generated improvements that rewrite the file and drop the front-matter; hand-edited SKILL.md files; content assembled by concatenation that puts prose before the front-matter block; editors saving with a BOM.","solutions":["Prepend a block that starts the file: ---\\nname: <slug>\\n---\\n followed by the body","Remove any leading blank lines, comments, or BOM bytes before the opening ---","Make sure the closing --- sits on its own line with a newline after the last front-matter key","Pre-validate with the public validate_skill_content before calling improve_skill"],"exampleFix":"# before (body only)\nHere is how to deploy...\n\n# after\n---\nname: deploy-guide\n---\nHere is how to deploy...","handlingStrategy":"validation","validationCode":"// Reuse the library's own public validator before the write path:\nzeroclaw_runtime::skills::validate_skill_content(&improved_content)?;\nimprover.improve_skill(slug, improved_content, reason).await?;","typeGuard":"fn has_yaml_front_matter(content: &str) -> bool {\n    let n = content.replace(\"\\r\\n\", \"\\n\");\n    match n.strip_prefix(\"---\\n\") {\n        Some(rest) => rest.contains(\"\\n---\\n\") || rest.ends_with(\"\\n---\"),\n        None => false,\n    }\n}","tryCatchPattern":"match improve_skill(...).await {\n    Err(e) if e.to_string().contains(\"missing YAML front-matter\") => {\n        // regenerate with the original front-matter preserved, then retry once\n    }\n    r => r,\n}","preventionTips":["When generating improvements, seed the prompt with the existing front-matter and require it verbatim in the output","Strip BOMs and leading blank lines before validation","Validate content shape before it ever reaches the improver"],"tags":["skills","skill-improver","yaml","front-matter","validation"],"backgroundTag":"yaml-frontmatter-missing","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}