affaan-m/ECC · error · ValueError

source_end_mode must be inclusive or exclusive

Error message

source_end_mode must be inclusive or exclusive

What it means

apply_placements requires source_end_mode to be given explicitly as 'inclusive' or 'exclusive'. Resolve hosts differ in whether the end frame is included in the source range; the library refuses to guess because a wrong guess yields off-by-one readback failures. This is validated before any timeline mutation.

Solutions

  1. Pass source_end_mode="inclusive" or "exclusive" explicitly after verifying the convention on your Resolve host
  2. Run the mode-validation tests (test_mode_must_be_explicit_and_valid) to confirm behavior
  3. Fix wrappers/config to forward only the two allowed strings
  4. Add a host-verification step in your pipeline that determines the convention once and records it

Example fix

// before
apply_placements(timeline, pool, placements, fps=fps, base_track_count=2)
// after
apply_placements(timeline, pool, placements, fps=fps, base_track_count=2, source_end_mode="exclusive")
Defensive patterns

Strategy: validation

Validate before calling

if source_end_mode not in ("inclusive", "exclusive"):
    raise ValueError("source_end_mode must be 'inclusive' or 'exclusive'")

Type guard

from typing import Literal
def is_valid_mode(m: str) -> bool:
    return m in ("inclusive", "exclusive")
Mode = Literal["inclusive", "exclusive"]

Try / catch

try:
    apply_placements(..., source_end_mode=mode)
except ValueError as exc:
    print(f"Fix source_end_mode: {exc}")
    raise

Prevention

When it happens

Trigger: Calling apply_placements/apply without source_end_mode, or with a value like ' Inclus ive', 'end-exclusive', or None.

Common situations: Copy-pasting an older call signature before the parameter existed; assuming a default; typo'd enum string; writing a generic wrapper that forwards user config unvalidated.

Understand the failure class

Background: "invalid argument", "unknown mode", "not supported": invalid enum-like argument errors explained — this error's family across 19 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/f162b3148d52b09f. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/scripts/tasteforge/resolve.py:251

    timeline,
    media_pool,
    placements,
    *,
    source_timeline,
    source_end_mode,
    fps,
    base_track_count,
    probe=probe_asset,
):
    """Append and verify overlays; returns an in-memory placement receipt only.

    This does not save/export/render a project. Supply the selected target's
    media pool. Existing overlay tracks must be empty; base tracks are preserved.
    source_end_mode is required: use the endpoint convention verified on this
    Resolve host. No automatic retry occurs if that convention is incorrect.
    """
    if source_end_mode not in ("inclusive", "exclusive"):
        raise ValueError("source_end_mode must be inclusive or exclusive")
    if not isinstance(source_timeline, str) or not source_timeline:
        raise ValueError("source_timeline must be explicit")
    name = timeline.GetName()
    if not name or name == source_timeline:
        raise ValueError("target must be a distinct versioned timeline")
    plan = allocate_placements(
        placements, fps=fps, base_track_count=base_track_count, probe=probe
    )
    if _fps(timeline.GetSetting("timelineFrameRate")) != _fps(fps):
        raise ValueError("target timeline fps mismatch")
    count = timeline.GetTrackCount("video")
    if count < base_track_count:
        raise ValueError("base_track_count exceeds target video tracks")
    for track in range(base_track_count + 1, count + 1):
        if _items(timeline, "video", track):
            raise ValueError("target overlay tracks must be empty")
    before = _base_snapshot(timeline, base_track_count)
    for _ in range(count, max(event["track"] for event in plan)):

View on GitHub (pinned to 8321021c54)