HKUDS/Vibe-Trading · error · ValueError

source.prompt is required

Error message

source.prompt is required

What it means

When draft.source.kind is 'prompt' (the default), source.prompt must be a non-empty string after stripping. This is the instruction the scheduler will run periodically.

Source

Thrown at agent/src/scheduled_research/service.py:138

    now = int(time.time() * 1000) if now_ms is None else now_ms
    title = str(draft.get("title") or "").strip()
    if not title:
        raise ValueError("title is required")
    source = draft.get("source")
    schedule_spec = draft.get("schedule")
    delivery_spec = draft.get("delivery") or {"mode": "in_app"}
    if not isinstance(source, Mapping) or not isinstance(schedule_spec, Mapping):
        raise ValueError("source and schedule must be objects")
    if not isinstance(delivery_spec, Mapping):
        raise ValueError("delivery must be an object")

    source_type = str(source.get("kind") or "prompt")
    playbook_slug = None
    config: dict[str, Any] = {}
    if source_type == "prompt":
        prompt = str(source.get("prompt") or "").strip()
        if not prompt:
            raise ValueError("source.prompt is required")
    elif source_type == "playbook":
        playbook_slug = str(source.get("playbook_slug") or "").strip()
        if not playbook_slug:
            raise ValueError("source.playbook_slug is required")
        playbook = get_playbook(playbook_slug)
        variables = source.get("variables") or {}
        if not isinstance(variables, Mapping):
            raise ValueError("source.variables must be an object")
        prompt = playbook.render(variables)
        config["playbook"] = playbook_slug
    else:
        raise ValueError("source.kind must be 'prompt' or 'playbook'")

    expression = str(schedule_spec.get("expression") or "").strip()
    timezone = schedule_spec.get("timezone")
    validate_schedule(expression)
    if is_interval_schedule(expression):
        validate_timezone_shape(timezone)

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Set source.prompt to the research instruction text
  2. If you meant a playbook, set kind='playbook' and playbook_slug instead
  3. Require the prompt field in client validation when kind is prompt

Example fix

// before
{"source": {"kind": "prompt"}}
// after
{"source": {"kind": "prompt", "prompt": "Summarize AI news"}}
Defensive patterns

Strategy: validation

Validate before calling

src = draft.get("source", {})
if str(src.get("kind") or "prompt") == "prompt":
    assert str(src.get("prompt") or "").strip(), "source.prompt is required"

Type guard

def prompt_source_valid(src: dict) -> bool:
    return str(src.get("kind") or "prompt") != "prompt" or bool(str(src.get("prompt") or "").strip())

Try / catch

try:
    propose_create(draft)
except ValueError as e:
    require_prompt_field() if "source.prompt" in str(e) else raise_

Prevention

When it happens

Trigger: source={"kind":"prompt"} with prompt omitted, empty, or whitespace; kind defaulted to 'prompt' because it was absent while prompt was also absent.

Common situations: Minimal drafts that only set schedule; UI where the prompt textarea is optional; templates with an empty prompt slot.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/a9ef8b9e7eca8fd7. Report an issue: GitHub.