affaan-m/ECC · error · RuntimeError

Resolve returned an item without an identity

Error message

Resolve returned an item without an identity

What it means

During readback, tasteforge identities each appended clip via GetUniqueId (falling back to id()). If Resolve returns an item whose identity is None, matching it against the placement's members is impossible, so this RuntimeError is raised as an internal invariant violation.

Solutions

  1. Upgrade/patch Resolve API usage — check the Resolve/Studio version's API for GetUniqueId support
  2. Re-acquire the timeline and retry after the append settles
  3. Inspect the track items to find the corrupted clip and remove/re-add it
  4. Extend identity() to reject/handle None early with a clearer probe of the item

Example fix

// before
method = getattr(candidate, "GetUniqueId", None)
return method() if callable(method) else id(candidate)
// after
method = getattr(candidate, "GetUniqueId", None)
uid = method() if callable(method) else None
if uid is None:
    raise RuntimeError(f"item {candidate.GetName() if hasattr(candidate,'GetName') else candidate} has no unique id")
return uid
Defensive patterns

Strategy: try-catch

Validate before calling

for item in members:
    uid = item.GetUniqueId() if callable(getattr(item, "GetUniqueId", None)) else None
    if uid is None:
        raise RuntimeError(f"item {item.GetName()} has no unique id")

Type guard

def has_identity(item) -> bool:
    m = getattr(item, "GetUniqueId", None)
    return callable(m) and m() is not None

Try / catch

try:
    result = apply_placements(...)
except RuntimeError as exc:
    if "without an identity" in str(exc):
        # re-acquire timeline and retry once
        timeline = project.GetCurrentTimeline()
    else:
        raise

Prevention

When it happens

Trigger: _readback iterating track items where a member's GetUniqueId returns None or is not callable and the object wraps None; Resolve API returning placeholder/invalid clip objects after append.

Common situations: Resolve version with changed/removed GetUniqueId behavior returning None; corrupted clip after failed import; API object garbage-collected mid-readback in a long-running session.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

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

                }
                for item in _items(timeline, kind, track)
            ]
    return snapshot


def _readback(timeline, item, event):
    track = event["track"]
    members = _items(timeline, "video", track)

    # API wrappers can be recreated on each call, so verify track membership by
    # stable unique id when available; test doubles may use object identity.
    def identity(candidate):
        method = getattr(candidate, "GetUniqueId", None)
        return method() if callable(method) else id(candidate)

    item_id = identity(item)
    if item_id is None:
        raise RuntimeError("Resolve returned an item without an identity")
    matches = [member for member in members if identity(member) == item_id]
    if len(matches) != 1:
        raise RuntimeError(f"placement {event['id']} missing from requested track")
    item = matches[0]
    actual = {
        "start": item.GetStart(),
        "end": item.GetEnd(),
        "duration": item.GetDuration(),
        "enabled": item.GetClipEnabled(),
        "track": track,
        "opacity": item.GetProperty("Opacity"),
        "composite": item.GetProperty("CompositeMode"),
        "path": _path(item),
    }
    expected = {
        "start": event["record_frame"],
        "end": event["record_frame"] + event["frames"],
        "duration": event["frames"],

View on GitHub (pinned to 8321021c54)