HKUDS/Vibe-Trading · error · ValueError
source.playbook_slug is required
Error message
source.playbook_slug is required
What it means
When draft.source.kind is 'playbook', source.playbook_slug must be a non-empty string. The slug selects the playbook template whose rendered output becomes the job's prompt.
Source
Thrown at agent/src/scheduled_research/service.py:142
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)
else:
validate_timezone(timezone)
next_run_at = now
if timezone is not None and not is_interval_schedule(expression):View on GitHub (pinned to 80ffdda44c)
Solutions
- Provide the exact playbook slug, e.g. source={"kind":"playbook","playbook_slug":"daily-digest"}
- Trim and verify the slug exists via get_playbook before submitting
- Make playbook selection mandatory when kind='playbook'
Example fix
// before
{"source": {"kind": "playbook", "playbook_slug": ""}}
// after
{"source": {"kind": "playbook", "playbook_slug": "daily-digest"}} Defensive patterns
Strategy: validation
Validate before calling
src = draft.get("source", {})
if src.get("kind") == "playbook":
assert str(src.get("playbook_slug") or "").strip(), "source.playbook_slug is required" Type guard
def playbook_source_valid(src: dict) -> bool:
return src.get("kind") != "playbook" or bool(str(src.get("playbook_slug") or "").strip()) Try / catch
try:
propose_create(draft)
except ValueError as e:
require_playbook_selection() if "playbook_slug" in str(e) else raise_ Prevention
- Make playbook selection a required dropdown when kind='playbook'
- Trim and existence-check slugs against the playbook registry before submit
When it happens
Trigger: source={"kind":"playbook"} with playbook_slug missing, empty, or whitespace-only; slug built from an unset variable.
Common situations: Playbook selection dropdown not required in the UI; slug strings with stray whitespace; renamed/deleted slugs referenced by value.
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
- playbook {self.slug!r} has no variable {key!r}; declared: {s
- playbook variable {key!r} is {len(text)} chars; the cap is {
- title is required
- source.prompt is required
- source.variables must be an object
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/63203c1f0d9e2693.
Report an issue: GitHub.