Comfy-Org/ComfyUI · error · ValueError

ASSET_NOT_FOUND

ASSET_NOT_FOUND

Error message

AssetReference {reference_id} not found

What it means

Raised by the ownership-verified reference fetch in app/assets/database/queries/asset_reference.py. It fires when get_reference_by_id returns no row OR when the row exists but deleted_at is not None (soft-deleted). The check deliberately treats soft-deleted references as nonexistent so callers never operate on tombstoned assets.

Source

Thrown at app/assets/database/queries/asset_reference.py:97

    reference_id: str,
) -> AssetReference | None:
    return session.get(AssetReference, reference_id)


def get_reference_with_owner_check(
    session: Session,
    reference_id: str,
    owner_id: str,
) -> AssetReference:
    """Fetch a reference and verify ownership.

    Raises:
        ValueError: if reference not found or soft-deleted
        PermissionError: if owner_id doesn't match
    """
    ref = get_reference_by_id(session, reference_id=reference_id)
    if not ref or ref.deleted_at is not None:
        raise ValueError(f"AssetReference {reference_id} not found")
    if ref.owner_id and ref.owner_id != owner_id:
        raise PermissionError("not owner")
    return ref


def get_reference_by_file_path(
    session: Session,
    file_path: str,
) -> AssetReference | None:
    """Get a reference by its file path."""
    return (
        session.execute(
            select(AssetReference).where(AssetReference.file_path == file_path).limit(1)
        )
        .scalars()
        .first()
    )

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Verify the reference_id is a real, non-deleted row first, e.g. via get_reference_by_id and checking deleted_at is None.
  2. If the ID came from a client, re-list references to obtain fresh IDs and retry.
  3. If the row is soft-deleted but needed, restore it by clearing deleted_at in the database (only if your workflow intentionally supports undelete).
  4. Confirm you are connected to the same database/session the reference was created in.

Example fix

// before
ref = get_reference_and_verify_owner(session, reference_id=rid, owner_id=uid)

// after
from app.assets.database.queries.asset_reference import get_reference_by_id
row = get_reference_by_id(session, reference_id=rid)
if not row or row.deleted_at is not None:
    # treat as 404: refresh IDs or skip
    return None
ref = get_reference_and_verify_owner(session, reference_id=rid, owner_id=uid)
Defensive patterns

Strategy: validation

Validate before calling

from app.assets.database.queries.asset_reference import get_reference_by_id

def reference_is_live(session, reference_id: str) -> bool:
    row = get_reference_by_id(session, reference_id=reference_id)
    return row is not None and row.deleted_at is None

Try / catch

try:
    ref = get_reference_and_verify_owner(session, reference_id=rid, owner_id=uid)
except ValueError as e:
    # 404 ASSET_NOT_FOUND
    ...
except PermissionError:
    # 403 FORBIDDEN
    ...

Prevention

When it happens

Trigger: Calling the fetch-and-verify function with a reference_id that was never created, was hard-deleted, or was soft-deleted (deleted_at set). Typical entry points: GET/PATCH/DELETE endpoints for a single reference that resolve the ID through this helper.

Common situations: Stale reference_id cached by a client after the asset was deleted; a rescan or mark-missing pass soft-deleting rows while an old UI tab still holds the ID; copy-pasting an ID with a typo or trailing whitespace; operating against a different database file than the one the reference was created in.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/c179f83eea397d15. Report an issue: GitHub.