calesthio/OpenMontage · error · SystemExit

Error: {path} must define at least one cut.

Error message

Error: {path} must define at least one cut.

What it means

Raised by render_demo.py's validate_props_file() as SystemExit when the demo props JSON loads successfully but its 'cuts' key is missing, not a list, or an empty list. The Remotion demo composition is driven entirely by the checked-in props file's cuts array; with zero cuts there is nothing to render, so the script aborts before invoking npx. This is a props-shape check: a plain JSON parse error would surface differently (from json.load), while this error is specifically about the cuts field.

Source

Thrown at render_demo.py:73

        raise SystemExit("Error: npm is required but was not found on PATH.")

    npx_cmd = find_command("npx.cmd", "npx", "npx.exe")
    if not npx_cmd:
        raise SystemExit("Error: npx is required but was not found on PATH.")

    if not (COMPOSER_DIR / "node_modules").exists():
        print("Installing Remotion dependencies...")
        subprocess.run([npm_cmd, "install"], cwd=COMPOSER_DIR, check=True)

    return npx_cmd


def validate_props_file(path: Path) -> None:
    with path.open("r", encoding="utf-8") as handle:
        payload = json.load(handle)

    if not isinstance(payload.get("cuts"), list) or not payload["cuts"]:
        raise SystemExit(f"Error: {path} must define at least one cut.")


def render_demo(name: str, props_path: Path, npx_cmd: str) -> None:
    validate_props_file(props_path)
    OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
    output_path = OUTPUT_DIR / f"{name}.mp4"

    print()
    print(f"Rendering: {name}")
    print(f"Props:     {props_path}")
    print(f"Output:    {output_path}")
    print()

    subprocess.run(
        [
            npx_cmd,
            "remotion",
            "render",

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Open the props file and ensure it has a top-level "cuts": [ ... ] array with at least one cut object.
  2. Compare against a working checked-in demo in PROPS_DIR and mirror its structure.
  3. If you renamed or restructured the field, rename it back to cuts.

Example fix

// props.json — before
{ "scenes": [{ "start": 0 }] }

// props.json — after
{ "cuts": [{ "start": 0, "end": 5, "label": "intro" }] }
Defensive patterns

Strategy: validation

Validate before calling

import json

def props_are_renderable(path) -> bool:
    with open(path) as f:
        payload = json.load(f)
    cuts = payload.get("cuts")
    return isinstance(cuts, list) and len(cuts) > 0

Type guard

from typing import Any

def has_valid_cuts(payload: dict[str, Any]) -> bool:
    cuts = payload.get("cuts")
    return isinstance(cuts, list) and bool(cuts) and all(isinstance(c, dict) for c in cuts)

Prevention

When it happens

Trigger: Passing a hand-written or edited props file whose top-level 'cuts' array was deleted, renamed (e.g. 'scenes'), or left empty; passing a props file from a different tool whose schema doesn't use cuts; a truncating edit that dropped the closing entries.

Common situations: Authoring a new demo by copying and trimming an existing props file down to nothing; schema drift after the composition changed its props shape; JSON with cuts: null.

Related errors


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