bytedance/deer-flow · error · PromptConfigurationError

Missing or empty 'messages' key in {path}

Error message

Missing or empty 'messages' key in {path}

What it means

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.

Source

Thrown at backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/prompt.py:166

        return _render_messages(raw_templates, variables, source_path)

    base = Path(prompts_dir) if prompts_dir else _PROMPTS_DEFAULT_DIR
    candidates: list[Path] = [base / f"{name}.chat.yaml"]
    if agent_name:
        candidates.insert(0, base / agent_name / f"{name}.chat.yaml")
    for path in candidates:
        if path.is_file():
            try:
                data = yaml.safe_load(path.read_text(encoding="utf-8"))
            except yaml.YAMLError as e:
                raise PromptConfigurationError(f"Invalid YAML in {path}: {e}") from e
            data = data or {}
            fmt = data.get("format", "chat")
            if fmt != "chat":
                raise PromptConfigurationError(f"Expected format='chat' in {path}, got {fmt!r}; use load_prompt() for text-format templates")
            msg_list = data.get("messages")
            if not isinstance(msg_list, list) or not msg_list:
                raise PromptConfigurationError(f"Missing or empty 'messages' key in {path}")
            raw_templates: list[dict[str, str]] = []
            for msg in msg_list:
                role = msg.get("role", "user")
                content = msg.get("content", "")
                if not isinstance(content, str):
                    content = str(content)
                raw_templates.append({"role": role, "content": content})
            _CHAT_TEMPLATE_CACHE[cache_key] = (raw_templates, str(path))
            return _render_messages(raw_templates, variables, str(path))
    searched = ", ".join(str(c) for c in candidates)
    raise FileNotFoundError(f"chat prompt template not found: {name} (searched: {searched})")


# Module-level aliases for the injected text sections (staleness_review /
# consolidation / fact_extraction). Each loads its bundled yaml template once
# at import. ``memory_update`` is NOT here -- it uses the chat form via
# :func:`load_prompt_messages` (system/user split, mirroring the lead agent's
# static system prompt).

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Open the named YAML file and add a non-empty messages list of role/content entries.
  2. If the template is meant to be plain text, keep format as text and use load_prompt() instead of load_prompt_messages().
  3. Validate prompt YAML with a schema check in CI (format in {chat,text}; chat requires non-empty list of messages).
  4. Restore the file from git history if a bad edit truncated it.

Example fix

# before (broken)
format: chat

# after
format: chat
messages:
  - role: system
    content: "You manage long-term memory."
  - role: user
    content: "{{ text }}"
Defensive patterns

Strategy: validation

Validate before calling

import yaml

def validate_chat_prompt(path):
    data = yaml.safe_load(path.read_text()) or {}
    msgs = data.get('messages')
    assert data.get('format') == 'chat', 'format must be chat'
    assert isinstance(msgs, list) and msgs, 'messages must be a non-empty list'
    assert all(isinstance(m.get('content'), (str,)) for m in msgs)

Type guard

def is_chat_prompt(data) -> bool:
    return (
        isinstance(data, dict)
        and data.get('format') == 'chat'
        and isinstance(data.get('messages'), list)
        and len(data['messages']) > 0
    )

Try / catch

try:
    msgs = load_prompt_messages('memory_update')
except PromptConfigurationError as e:
    raise RuntimeError(f'prompt template misconfigured: {e}; fix the YAML messages block') from e

Prevention

When it happens

Trigger: 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: [].

Common situations: 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.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/c1a8bf35e38fe54e. Report an issue: GitHub.