{"record":{"id":"0ee4ca6e3576512e","repo":"zeroclaw-labs/zeroclaw","slug":"skill-front-matter-missing-required-name-field","errorCode":null,"errorMessage":"Skill front-matter missing required `name` field","messagePattern":"Skill front-matter missing required `name` field","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/skills/improver.rs","lineNumber":145,"sourceCode":"    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()))\n    } else {\n        rest.strip_suffix(\"\\n---\")\n            .map(|front| (front.to_string(), String::new()))\n    }\n}","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/skills/improver.rs#L127-L163","documentation":"Front-matter was found, but front_matter_value found no top-level 'name:' key, or one whose value is empty after quote stripping. name is the only required front-matter field for a skill the improver is allowed to write back.","triggerScenarios":"Front-matter with no name key at all; 'name:' with an empty value or empty quotes; name nested under another mapping (indented lines are skipped by the flat key parser); a differently spelled key such as title or skill_name.","commonSituations":"LLM improvement that renames or drops the field; templates that use title instead of name; YAML where name sits under a nested metadata: block.","solutions":["Add an unindented top-level line 'name: <value>' inside the front-matter","Give it a real value: name: \\\"\\\" also fails the empty check","If name is nested (e.g., under metadata:), move it to the top level","Pre-validate with the public validate_skill_content before calling improve_skill"],"exampleFix":"# before\n---\ntitle: deploy-guide\n---\n\n# after\n---\nname: deploy-guide\n---","handlingStrategy":"type-guard","validationCode":"zeroclaw_runtime::skills::validate_skill_content(&improved_content)?; // rejects missing name too","typeGuard":"fn front_matter_has_name(content: &str) -> bool {\n    let n = content.replace(\"\\r\\n\", \"\\n\");\n    let Some(rest) = n.strip_prefix(\"---\\n\") else { return false };\n    let front = rest.split(\"\\n---\\n\").next().unwrap_or(rest);\n    front.lines().any(|l| {\n        !l.starts_with(' ') && !l.starts_with('\\t')\n            && l.starts_with(\"name:\")\n            && l[5..].trim().trim_matches('\"').trim_matches('\\'').trim().len() > 0\n    })\n}","tryCatchPattern":null,"preventionTips":["Pin the name field in generation prompts so the model cannot drop or rename it","Use 'name', not 'title' or 'skill_name', at the top level of the front-matter","Pre-validate with the library's public validate_skill_content before writing"],"tags":["skills","skill-improver","yaml","front-matter","validation"],"backgroundTag":"frontmatter-required-field-missing","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}