{"record":{"id":"e9fdd82e2214d72f","repo":"crewAIInc/crewAI","slug":"no-yaml-frontmatter-block-found","errorCode":null,"errorMessage":"No YAML frontmatter block found","messagePattern":"No YAML frontmatter block found","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/cli/src/crewai_cli/skills/main.py","lineNumber":398,"sourceCode":"        \"\"\"Extract YAML frontmatter fields from a SKILL.md string.\n\n        Reuses crewai.skills.parser when available, with a minimal\n        fallback for environments where the full SDK isn't installed.\n        \"\"\"\n        try:\n            from crewai.skills.parser import parse_frontmatter\n\n            fm_dict, _ = parse_frontmatter(content)\n            return fm_dict\n        except ImportError:\n            pass\n\n        # Fallback: minimal YAML parsing without SDK dependency\n        import re\n\n        match = re.match(r\"^---\\n(.*?)\\n---\", content, re.DOTALL)\n        if not match:\n            raise ValueError(\"No YAML frontmatter block found\")\n        try:\n            import yaml\n\n            return yaml.safe_load(match.group(1)) or {}\n        except ImportError:\n            result: dict[str, str] = {}\n            for line in match.group(1).splitlines():\n                if \":\" in line:\n                    key, _, value = line.partition(\":\")\n                    result[key.strip()] = value.strip()\n            return result\n\n    def _read_version(self, skill_md: Path) -> str | None:\n        \"\"\"Read the version from a SKILL.md file's metadata, or None.\"\"\"\n        try:\n            fm = self._parse_frontmatter(skill_md.read_text(encoding=\"utf-8\"))\n            raw_metadata = fm.get(\"metadata\")\n            if isinstance(raw_metadata, dict):","sourceCodeStart":380,"sourceCodeEnd":416,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/cli/src/crewai_cli/skills/main.py#L380-L416","documentation":"The fallback frontmatter parser (used when the SDK's `crewai.skills.parser` is not importable) looks for a `^---\\n...\\n---` block at the very start of the file. If the regex does not match — no delimiters, a leading blank line/BOM, CRLF line endings, or `---` not on line 1 — it raises `ValueError(\"No YAML frontmatter block found\")`, which surfaces as error 70's message.","triggerScenarios":"Calling `_parse_frontmatter` (via `crewai skill publish`) on a SKILL.md that does not begin with `---\\n`; a UTF-8 BOM before the first `---`; Windows CRLF line breaks; or frontmatter delimiters written as `----`. The SDK parser is bypassed only when the crewai SDK package is absent.","commonSituations":"Files saved on Windows with CRLF; editors that insert a BOM; manually authored SKILL.md missing delimiters; older CLI installs without the SDK installed so the fallback path runs.","solutions":["Ensure SKILL.md starts with `---` on the very first byte, ends the block with a second `---`, and uses LF line endings (`dos2unix SKILL.md`).","Install/upgrade the crewai SDK so the more robust `parse_frontmatter` is used instead of the strict regex fallback.","Remove any BOM: `sed -i '1s/^\\xEF\\xBB\\xBF//' SKILL.md`."],"exampleFix":"# before\n\n---\nname: x\n---\n(body)\n\n# after\n---\nname: x\n---\n(body)","handlingStrategy":"validation","validationCode":"from pathlib import Path\nimport re\n\ndef frontmatter_block_at_start(path: str = \"SKILL.md\") -> bool:\n    raw = Path(path).read_bytes()\n    if raw.startswith(b\"\\xef\\xbb\\xbf\"):\n        return False  # BOM breaks the regex\n    return bool(re.match(rb\"^---\\n.*?\\n---\", raw, re.DOTALL))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Save SKILL.md with LF line endings and no BOM (UTF-8 plain).","Put `---` on the very first line; no leading blank lines.","Install the crewai SDK so the robust parser is used instead of the strict fallback regex."],"tags":["cli","yaml","frontmatter","encoding","skill"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}