HKUDS/Vibe-Trading · error · PlaybookError

playbook variable {key!r} is {len(text)} chars; the cap is {

Error message

playbook variable {key!r} is {len(text)} chars; the cap is {_MAX_VARIABLE_CHARS}

What it means

Raised by Playbook.render (agent/src/scheduled_research/playbooks.py:133) as PlaybookError when a supplied variable value, after str() and strip(), exceeds the maximum allowed character count (_MAX_VARIABLE_CHARS). The cap limits how much injected text can land in the rendered prompt body.

Source

Thrown at agent/src/scheduled_research/playbooks.py:133

                is not declared by this playbook is an error rather than a
                silent no-op. A blank value falls back to the declared default.

        Returns:
            The prompt text to hand to the scheduler.

        Raises:
            PlaybookError: If an undeclared variable is supplied or a value
                exceeds the length cap.
        """
        values = dict(self.variables)
        for key, raw in (variables or {}).items():
            if key not in values:
                raise PlaybookError(
                    f"playbook {self.slug!r} has no variable {key!r}; declared: {sorted(values)}"
                )
            text = str(raw).strip()
            if len(text) > _MAX_VARIABLE_CHARS:
                raise PlaybookError(
                    f"playbook variable {key!r} is {len(text)} chars; the cap is {_MAX_VARIABLE_CHARS}"
                )
            if text:
                values[key] = text
        # Every placeholder in the body was checked against ``variables`` at
        # load time, so this substitution cannot leave one behind.
        return _PLACEHOLDER_RE.sub(lambda m: values[m.group(1)], self.body)

    def to_job(
        self,
        *,
        job_id: Optional[str] = None,
        schedule: Optional[str] = None,
        timezone: Any = _KEEP,
        variables: Optional[Mapping[str, Any]] = None,
        config: Optional[Mapping[str, Any]] = None,
        next_run_at: Optional[int] = None,
        now_ms: Optional[int] = None,

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Truncate before calling render: value[:cap] (read _MAX_VARIABLE_CHARS from the module)
  2. Summarize long content upstream instead of truncating blindly
  3. Validate input length at your API boundary with the same cap
  4. Split oversized content across multiple runs or a different mechanism

Example fix

# before
job = playbook.to_job(schedule="@daily", variables={"topic": huge_text})

# after
from agent.src.scheduled_research.playbooks import _MAX_VARIABLE_CHARS
job = playbook.to_job(schedule="@daily", variables={"topic": huge_text[:_MAX_VARIABLE_CHARS]})
Defensive patterns

Strategy: validation

Validate before calling

from agent.src.scheduled_research.playbooks import _MAX_VARIABLE_CHARS

def within_cap(text):
    return len(str(text).strip()) <= _MAX_VARIABLE_CHARS

Type guard

from agent.src.scheduled_research.playbooks import _MAX_VARIABLE_CHARS
from typing import Any

def capped(value: Any) -> str:
    text = str(value).strip()
    return text[:_MAX_VARIABLE_CHARS]

Try / catch

from agent.src.scheduled_research.playbooks import PlaybookError

try:
    job = playbook.to_job(schedule="@daily", variables=vars)
except PlaybookError as exc:
    if "the cap is" in str(exc):
        vars = {k: str(v).strip()[:_MAX_VARIABLE_CHARS] for k, v in vars.items()}
        job = playbook.to_job(schedule="@daily", variables=vars)
    else:
        raise

Prevention

When it happens

Trigger: Passing a long topic description, pasted article text, or a multi-paragraph value to to_job/build_job_from_draft where the value's stripped length exceeds the cap constant defined in playbooks.py.

Common situations: Feeding user free-text input or LLM-generated content into a variable; progressive scope creep in prompt content; copying a full document where a summary was intended.

Related errors


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