{"record":{"id":"50b32421d85737cd","repo":"OpenBMB/ChatDev","slug":"missing-closing-delimiter","errorCode":null,"errorMessage":"missing closing delimiter","messagePattern":"missing closing delimiter","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"entity/configs/node/skills.py","lineNumber":58,"sourceCode":"            continue\n        if not isinstance(raw_description, str) or not raw_description.strip():\n            continue\n        discovered.append((raw_name.strip(), raw_description.strip()))\n    return discovered\n\n\ndef _parse_frontmatter(skill_file: Path) -> Mapping[str, object]:\n    text = skill_file.read_text(encoding=\"utf-8\")\n    if not text.startswith(\"---\"):\n        raise ValueError(\"missing frontmatter\")\n    lines = text.splitlines()\n    end_idx = None\n    for idx in range(1, len(lines)):\n        if lines[idx].strip() == \"---\":\n            end_idx = idx\n            break\n    if end_idx is None:\n        raise ValueError(\"missing closing delimiter\")\n    payload = \"\\n\".join(lines[1:end_idx])\n    data = yaml.safe_load(payload) or {}\n    if not isinstance(data, Mapping):\n        raise ValueError(\"frontmatter must be a mapping\")\n    return data\n\n\n@dataclass\nclass AgentSkillSelectionConfig(BaseConfig):\n    name: str\n\n    FIELD_SPECS = {\n        \"name\": ConfigFieldSpec(\n            name=\"name\",\n            display_name=\"Skill Name\",\n            type_hint=\"str\",\n            required=True,\n            description=\"Discovered skill name from the default repo-level skills directory.\",","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/OpenBMB/ChatDev/blob/4fb2db0ea90375ce1059f44fe03ffbd191a7a169/entity/configs/node/skills.py#L40-L76","documentation":"After finding the opening '---', _parse_frontmatter scans for a matching closing '---' line; if none exists before EOF it raises ValueError('missing closing delimiter'). The YAML frontmatter block is unterminated.","triggerScenarios":"A skill markdown file with an opening '---' but no second '---' line terminating the frontmatter block.","commonSituations":"Truncated files; authors forgetting the closing delimiter; copy-paste that drops the last line; a horizontal-rule '---' being confused with delimiters mid-document after the real block was never closed.","solutions":["Add a closing '---' line after the YAML block on its own line","Verify the file is complete (not truncated by a failed write or partial download)","Run a quick lint: file must contain at least two lines equal to '---'"],"exampleFix":"# before\n---\nname: my-skill\n# after\n---\nname: my-skill\n---","handlingStrategy":"validation","validationCode":"lines = text.splitlines()\nassert any(l.strip() == '---' for l in lines[1:]), 'unterminated frontmatter'","typeGuard":null,"tryCatchPattern":"try:\n    _discover_default_skills(skills_dir)\nexcept ValueError as e:\n    if 'closing delimiter' in str(e):\n        # quarantine file, log, continue\n        ...","preventionTips":["Lint that '---' appears at least twice","Atomic-write skill files to avoid truncation"],"tags":["skills","frontmatter","markdown","parsing"],"backgroundTag":"malformed-frontmatter","analyzedSha":"4fb2db0ea90375ce1059f44fe03ffbd191a7a169","analyzedAt":"2026-08-27T14:35:29.622Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}