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
- Verify the reference_id is a real, non-deleted row first, e.g. via get_reference_by_id and checking deleted_at is None.
- If the ID came from a client, re-list references to obtain fresh IDs and retry.
- If the row is soft-deleted but needed, restore it by clearing deleted_at in the database (only if your workflow intentionally supports undelete).
- 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
- Always fetch fresh reference IDs from a list endpoint before acting on a single reference.
- Treat soft-deleted rows (deleted_at set) as nonexistent in client logic.
- Map ValueError to 404 and PermissionError to 403 at the API boundary so both are distinguishable.
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.