calesthio/OpenMontage · error · CheckpointValidationError

Checkpoint failed schema validation: {exc.message}

Error message

Checkpoint failed schema validation: {exc.message}

What it means

ffprobe succeeded but the measured audio duration is outside 2–max_seconds (default 15): either shorter than 2 seconds or longer than 15. Note ffprobe failure paths produce duration=0, so an unprobeable file also surfaces here as 'too short', and a ValueError from float() lands in the probe-failure error instead.

Source

Thrown at lib/checkpoint.py:191

        else ALL_KNOWN_STAGES
    )

    if not isinstance(stage, str) or stage not in valid_stages:
        raise CheckpointValidationError(
            f"Invalid stage: {stage!r} for pipeline {pipeline_type!r}. "
            f"Valid stages: {sorted(valid_stages)}"
        )
    if not isinstance(status, str):
        raise CheckpointValidationError(f"Invalid status: {status!r}")
    if not isinstance(artifacts, dict):
        raise CheckpointValidationError("Checkpoint artifacts must be a dictionary")

    _validate_artifacts_for_stage(stage, status, artifacts)

    try:
        jsonschema.validate(instance=checkpoint, schema=_load_checkpoint_schema())
    except jsonschema.ValidationError as exc:
        raise CheckpointValidationError(f"Checkpoint failed schema validation: {exc.message}") from exc


def _checkpoint_path(pipeline_dir: Path, project_id: str, stage: str) -> Path:
    return pipeline_dir / project_id / f"checkpoint_{stage}.json"


def init_project(
    project_id: str,
    *,
    title: str,
    pipeline_type: str,
    pipeline_dir: Optional[Path] = None,
    style_playbook: Optional[str] = None,
) -> Path:
    """Initialize a project workspace with the canonical layout + marker file.

    Creates projects/<project_id>/ with the standard subdirectories and writes
    project.json — the marker the Backlot board uses to render a project's

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Trim the clip to 2–15 seconds: ffmpeg -i in.mp3 -ss 0 -t 10 out.mp3.
  2. If duration reads 0, verify with ffprobe manually and re-mux/re-encode the container.
  3. For longer audio, pass several short reference clips instead of one long one.

Example fix

# before
inputs = {"reference_audio_path": "full_song.mp3"}
# after
# run: ffmpeg -i full_song.mp3 -ss 30 -t 10 clip.mp3
inputs = {"reference_audio_path": "clip.mp3"}
Defensive patterns

Strategy: validation

Validate before calling

import subprocess
out = subprocess.run(["ffprobe", "-v", "error", "-show_entries", "format=duration",
                      "-of", "default=noprint_wrappers=1:nokey=1", ref],
                     capture_output=True, text=True, check=True).stdout
dur = float(out.strip())
assert 2 <= dur <= 15, dur

Type guard

def audio_duration_ok(seconds: float) -> bool:
    return 2 <= seconds <= 15

Try / catch

try:
    tool.run(inputs)
except ValueError as e:
    if "2 to" in str(e) and "seconds" in str(e):
        trim_to_range(ref)  # ffmpeg -ss/-t to 2-15s, retry
    else:
        raise

Prevention

When it happens

Trigger: A 1s beep/wav as reference audio; a full 3-minute song passed as reference_audio; a corrupt file whose probe yields 0.

Common situations: Voice clips trimmed too aggressively; trying to seed audio style from a complete track instead of a short excerpt; format-mismatch files where ffprobe reports 0 duration.

Related errors


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