{"record":{"id":"2519fcbb22340cd1","repo":"datawhalechina/hello-agents","slug":"yaml","errorCode":null,"errorMessage":"无效的笔记格式：缺少YAML前置元数据","messagePattern":"无效的笔记格式：缺少YAML前置元数据","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/YYHDBL-HelloCodeAgentCli/tools/builtin/note_tool.py","lineNumber":154,"sourceCode":"            tags_str = json.dumps(note['tags'])\n            frontmatter += f\"tags: {tags_str}\\n\"\n        frontmatter += f\"created_at: {note['created_at']}\\n\"\n        frontmatter += f\"updated_at: {note['updated_at']}\\n\"\n        frontmatter += \"---\\n\\n\"\n        \n        # Markdown内容\n        content = f\"# {note['title']}\\n\\n\"\n        content += note['content']\n        \n        return frontmatter + content\n    \n    def _markdown_to_note(self, markdown_text: str) -> Dict[str, Any]:\n        \"\"\"将Markdown文本解析为笔记对象\"\"\"\n        # 提取YAML前置元数据\n        frontmatter_match = re.match(r'^---\\s*\\n(.*?)\\n---\\s*\\n', markdown_text, re.DOTALL)\n        \n        if not frontmatter_match:\n            raise ValueError(\"无效的笔记格式：缺少YAML前置元数据\")\n        \n        frontmatter_text = frontmatter_match.group(1)\n        content_start = frontmatter_match.end()\n        \n        # 解析YAML（简化版）\n        note = {}\n        for line in frontmatter_text.split('\\n'):\n            if ':' in line:\n                key, value = line.split(':', 1)\n                key = key.strip()\n                value = value.strip()\n                \n                # 处理特殊字段\n                if key == 'tags':\n                    try:\n                        note[key] = json.loads(value)\n                    except:\n                        note[key] = []","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/YYHDBL-HelloCodeAgentCli/tools/builtin/note_tool.py#L136-L172","documentation":"ValueError from NoteTool._markdown_to_note when the markdown text does not begin with a '---\\n...\\n---\\n' YAML frontmatter block (regex re.match with DOTALL anchors at position 0). Every stored note is round-tripped as frontmatter + body, so text lacking the leading delimiters cannot be parsed back into a note object.","triggerScenarios":"Calling the note tool's parse/read path with plain markdown that has no frontmatter; a leading blank line or BOM before the first '---' so re.match fails; frontmatter delimiters using '----' or missing the closing '---'.","commonSituations":"Users pasting raw markdown into a note-read/list operation; hand-edited note files where the frontmatter was deleted; files created by other tools (Obsidian requires exact '---' first line too); trailing spaces after '---' are tolerated by \\s* but a preceding empty line is not.","solutions":["Ensure the note file starts, on line 1, with '---', then YAML keys, then a closing '---' before the body.","Strip leading whitespace/BOM before parsing: markdown_text.lstrip('\\ufeff').lstrip().","If reading foreign markdown, skip note parsing or synthesize frontmatter (title/date) first."],"exampleFix":"# before (parse fails)\ntext = '# My Note\\n\\nbody...'  \nnote = tool._markdown_to_note(text)\n\n# after\ntext = '---\\ntitle: My Note\\ncreated: 2026-01-01\\n---\\n\\n# My Note\\n\\nbody...'\nnote = tool._markdown_to_note(text)","handlingStrategy":"try-catch","validationCode":"def has_frontmatter(md: str) -> bool:\n    return bool(re.match(r'^---\\s*\\n.*?\\n---\\s*(\\n|$)', md, re.DOTALL))\n\nif not has_frontmatter(text):\n    text = f'---\\ntitle: untitled\\n---\\n\\n{text}'  # or reject","typeGuard":"def is_note_markdown(md: str) -> bool:\n    first = md.lstrip('\\ufeff').splitlines()[0] if md.strip() else ''\n    return first.strip() == '---'","tryCatchPattern":"try:\n    note = tool._markdown_to_note(md)\nexcept ValueError as e:\n    if 'YAML' in str(e):\n        md = f'---\\ntitle: imported\\n---\\n\\n{md}'\n        note = tool._markdown_to_note(md)\n    else:\n        raise","preventionTips":["Always write notes through the tool so frontmatter is generated.","Keep '---' as the literal first line; no leading blank lines or BOM.","Validate imported markdown before parsing."],"tags":["note-tool","markdown","parsing","yaml-frontmatter"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}