calesthio/OpenMontage · error · ValueError

Unknown step kind: {k!r}

Error message

Unknown step kind: {k!r}

What it means

Raised by lib/verify_scene_pacing.py's step_duration() when a scene step dict has a 'kind' value other than the four supported kinds: 'cmd', 'out', 'pause', 'pill'. Each kind has its own duration model — 'cmd' types text at typeSpeed (default 0.035s/char) plus holdSeconds (default 0.3), 'out' is a reveal of ~0.08s plus holdSeconds (default 0.15), 'pause' is its explicit seconds, 'pill' is instant (0.0). An unknown kind means the pacing verifier cannot compute the timeline and refuses to guess.

Source

Thrown at lib/verify_scene_pacing.py:49


def step_duration(step: dict[str, Any], fps: int = 30) -> float:
    """Return the cursor-advancement for a single step (frame-accurate).

    Pills DO NOT advance the cursor — they're non-blocking overlays.
    """
    k = step["kind"]
    if k == "cmd":
        type_frames = math.ceil(len(step["text"]) * step.get("typeSpeed", 0.035) * fps)
        return type_frames / fps + step.get("holdSeconds", 0.3)
    if k == "out":
        reveal_frames = max(2, math.ceil(0.08 * fps))
        return reveal_frames / fps + step.get("holdSeconds", 0.15)
    if k == "pause":
        return float(step["seconds"])
    if k == "pill":
        return 0.0
    raise ValueError(f"Unknown step kind: {k!r}")


@dataclass
class Landmark:
    video_time: float
    kind: str
    text: str


def trace(steps: list[dict[str, Any]], scene_start: float = 0.0, fps: int = 30, *, quiet: bool = False) -> list[Landmark]:
    """Walk the step list and print a video-time landmark for each visible event.

    Returns the list of landmarks (useful for alignment checks).
    """
    cursor = 0.0
    out: list[Landmark] = []
    for s in steps:
        k = s["kind"]

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Correct the step to one of the four kinds: cmd, out, pause, pill (use 'pause' with seconds for waits).
  2. Validate kinds before tracing: assert all(s['kind'] in {'cmd','out','pause','pill'} for s in steps).
  3. If you added a new kind to the renderer, add a matching duration branch to step_duration() in lib/verify_scene_pacing.py.

Example fix

# before
steps = [{"kind": "wait", "seconds": 2.0}]

# after
steps = [{"kind": "pause", "seconds": 2.0}]
Defensive patterns

Strategy: type-guard

Validate before calling

VALID_KINDS = {"cmd", "out", "pause", "pill"}
bad = [i for i, s in enumerate(steps) if s.get("kind") not in VALID_KINDS]
if bad:
    raise ValueError(f"Invalid step kind at indices {bad}; valid kinds: {sorted(VALID_KINDS)}")

Type guard

from typing import Literal
StepKind = Literal["cmd", "out", "pause", "pill"]

def steps_are_valid(steps: list[dict]) -> bool:
    return all(s.get("kind") in {"cmd", "out", "pause", "pill"} for s in steps)

Try / catch

try:
    trace(steps, scene_start, fps)
except ValueError as e:
    if "Unknown step kind" in str(e):
        # bad generated steps — regenerate or repair before verifying pacing
        raise SceneStepError(str(e)) from e
    raise

Prevention

When it happens

Trigger: Feeding assert_alignment()/trace() a steps list containing a step like {'kind': 'wait', 'seconds': 2} or a typo like {'kind': 'cmdd'}; generating steps with a template or LLM that invents kind values; using a new step kind added to the renderer but not to this verifier.

Common situations: Hand-written or machine-generated scene step YAML with kind typos; renderer and verifier drifting out of sync when a new step kind is introduced; copy-pasting steps from a different scene format.

Related errors


AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15). Data as JSON: /api/errors/44e52bae7e8dee3f. Report an issue: GitHub.