{"record":{"id":"01411665f218bea4","repo":"warpdotdev/warp","slug":"skill-md-missing-frontmatter-no-opening","errorCode":null,"errorMessage":"SKILL.md missing frontmatter (no opening ---)","messagePattern":"SKILL\\.md missing frontmatter \\(no opening ---\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"resources/bundled/skills/create-skill/scripts/utils.py","lineNumber":13,"sourceCode":"\"\"\"Shared utilities for skill-creator scripts.\"\"\"\n\nfrom pathlib import Path\n\n\n\ndef parse_skill_md(skill_path: Path) -> tuple[str, str, str]:\n    \"\"\"Parse a SKILL.md file, returning (name, description, full_content).\"\"\"\n    content = (skill_path / \"SKILL.md\").read_text()\n    lines = content.split(\"\\n\")\n\n    if lines[0].strip() != \"---\":\n        raise ValueError(\"SKILL.md missing frontmatter (no opening ---)\")\n\n    end_idx = None\n    for i, line in enumerate(lines[1:], start=1):\n        if line.strip() == \"---\":\n            end_idx = i\n            break\n\n    if end_idx is None:\n        raise ValueError(\"SKILL.md missing frontmatter (no closing ---)\")\n\n    name = \"\"\n    description = \"\"\n    frontmatter_lines = lines[1:end_idx]\n    i = 0\n    while i < len(frontmatter_lines):\n        line = frontmatter_lines[i]\n        if line.startswith(\"name:\"):\n            name = line[len(\"name:\"):].strip().strip('\"').strip(\"'\")","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/warpdotdev/warp/blob/e72fd7aacbbb2236d9b3be2aad7e7178fe94b4bc/resources/bundled/skills/create-skill/scripts/utils.py#L1-L31","documentation":"parse_skill_md() in create-skill's utils.py splits SKILL.md on newlines and requires the very first line (after strip) to be '---', the YAML frontmatter opening delimiter. Any file not opening with --- is rejected before name/description parsing, because frontmatter is the only place the skill's name and description are read from.","triggerScenarios":"SKILL.md starting with a blank line, a UTF-8 BOM, a heading like '# My Skill', or prose; calling parse_skill_md on a directory holding a README-style markdown instead of a frontmattered SKILL.md.","commonSituations":"Hand-written skills pasted from chat output that lost the frontmatter; editors or scaffolds inserting content above the delimiter; files saved with a BOM by Windows editors.","solutions":["Make line 1 exactly --- and close the block with a second --- line","Put name: and description: inside the block (the parser handles > and | multiline indicators for long descriptions)","Re-save as UTF-8 without a BOM — lines[0].strip() still fails on a BOM-prefixed first line"],"exampleFix":"# before\n# My Cool Skill\n\nSome intro text.\n\n---\nname: my-skill\n\n# after\n---\nname: my-skill\ndescription: Does one thing well.\n---\n\n# My Cool Skill","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\nlines = (skill_path / 'SKILL.md').read_text(encoding='utf-8').splitlines()\nif not lines or lines[0].strip() != '---':\n    raise ValueError(f'{skill_path}/SKILL.md must open with a --- frontmatter block')","typeGuard":null,"tryCatchPattern":"try:\n    name, description, content = parse_skill_md(skill_path)\nexcept ValueError as e:\n    # report the skill directory alongside the parser's message\n    raise SystemExit(f'{skill_path}: {e}') from e","preventionTips":["Scaffold skills from a template that includes both --- delimiters","Save SKILL.md as UTF-8 without BOM","Lint frontmatter in CI for every skill directory"],"tags":["markdown","frontmatter","parsing","skills"],"backgroundTag":null,"analyzedSha":"e72fd7aacbbb2236d9b3be2aad7e7178fe94b4bc","analyzedAt":"2026-08-16T08:27:25.381Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}