{"record":{"id":"c1a8bf35e38fe54e","repo":"bytedance/deer-flow","slug":"missing-or-empty-messages-key-in-path","errorCode":null,"errorMessage":"Missing or empty 'messages' key in {path}","messagePattern":"Missing or empty 'messages' key in (.+?)","errorType":"exception","errorClass":"PromptConfigurationError","httpStatus":null,"severity":"error","filePath":"backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/prompt.py","lineNumber":166,"sourceCode":"        return _render_messages(raw_templates, variables, source_path)\n\n    base = Path(prompts_dir) if prompts_dir else _PROMPTS_DEFAULT_DIR\n    candidates: list[Path] = [base / f\"{name}.chat.yaml\"]\n    if agent_name:\n        candidates.insert(0, base / agent_name / f\"{name}.chat.yaml\")\n    for path in candidates:\n        if path.is_file():\n            try:\n                data = yaml.safe_load(path.read_text(encoding=\"utf-8\"))\n            except yaml.YAMLError as e:\n                raise PromptConfigurationError(f\"Invalid YAML in {path}: {e}\") from e\n            data = data or {}\n            fmt = data.get(\"format\", \"chat\")\n            if fmt != \"chat\":\n                raise PromptConfigurationError(f\"Expected format='chat' in {path}, got {fmt!r}; use load_prompt() for text-format templates\")\n            msg_list = data.get(\"messages\")\n            if not isinstance(msg_list, list) or not msg_list:\n                raise PromptConfigurationError(f\"Missing or empty 'messages' key in {path}\")\n            raw_templates: list[dict[str, str]] = []\n            for msg in msg_list:\n                role = msg.get(\"role\", \"user\")\n                content = msg.get(\"content\", \"\")\n                if not isinstance(content, str):\n                    content = str(content)\n                raw_templates.append({\"role\": role, \"content\": content})\n            _CHAT_TEMPLATE_CACHE[cache_key] = (raw_templates, str(path))\n            return _render_messages(raw_templates, variables, str(path))\n    searched = \", \".join(str(c) for c in candidates)\n    raise FileNotFoundError(f\"chat prompt template not found: {name} (searched: {searched})\")\n\n\n# Module-level aliases for the injected text sections (staleness_review /\n# consolidation / fact_extraction). Each loads its bundled yaml template once\n# at import. ``memory_update`` is NOT here -- it uses the chat form via\n# :func:`load_prompt_messages` (system/user split, mirroring the lead agent's\n# static system prompt).","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/prompt.py#L148-L184","documentation":"PromptConfigurationError from load_prompt_messages: a chat-format YAML prompt file was found, but its top-level 'messages' key is missing, not a list, or an empty list. The deermem prompt loader requires chat templates to carry format: 'chat' plus a non-empty messages list of {role, content} entries.","triggerScenarios":"load_prompt_messages(name) resolves a YAML file whose content is, e.g., a plain string template, has only 'format: chat' with no messages, messages: {} (dict not list), or messages: [].","commonSituations":"A text-format template mistakenly given format: 'chat'; hand-edited prompt YAML that dropped the messages block; a template truncated by a merge conflict; switching a prompt from text to chat form without restructuring the YAML.","solutions":["Open the named YAML file and add a non-empty messages list of role/content entries.","If the template is meant to be plain text, keep format as text and use load_prompt() instead of load_prompt_messages().","Validate prompt YAML with a schema check in CI (format in {chat,text}; chat requires non-empty list of messages).","Restore the file from git history if a bad edit truncated it."],"exampleFix":"# before (broken)\nformat: chat\n\n# after\nformat: chat\nmessages:\n  - role: system\n    content: \"You manage long-term memory.\"\n  - role: user\n    content: \"{{ text }}\"","handlingStrategy":"validation","validationCode":"import yaml\n\ndef validate_chat_prompt(path):\n    data = yaml.safe_load(path.read_text()) or {}\n    msgs = data.get('messages')\n    assert data.get('format') == 'chat', 'format must be chat'\n    assert isinstance(msgs, list) and msgs, 'messages must be a non-empty list'\n    assert all(isinstance(m.get('content'), (str,)) for m in msgs)","typeGuard":"def is_chat_prompt(data) -> bool:\n    return (\n        isinstance(data, dict)\n        and data.get('format') == 'chat'\n        and isinstance(data.get('messages'), list)\n        and len(data['messages']) > 0\n    )","tryCatchPattern":"try:\n    msgs = load_prompt_messages('memory_update')\nexcept PromptConfigurationError as e:\n    raise RuntimeError(f'prompt template misconfigured: {e}; fix the YAML messages block') from e","preventionTips":["Lint all bundled prompt YAML in CI (format + messages shape).","Use the chat template only for chat prompts; text templates go through load_prompt().","Template unit tests that render every bundled prompt catch broken files before deploy."],"tags":["prompt","yaml","config","deermem","memory"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}