{"record":{"id":"c179f83eea397d15","repo":"Comfy-Org/ComfyUI","slug":"asset-not-found","errorCode":"ASSET_NOT_FOUND","errorMessage":"AssetReference {reference_id} not found","messagePattern":"AssetReference (.+?) not found","errorType":"exception","errorClass":"ValueError","httpStatus":404,"severity":"error","filePath":"app/assets/database/queries/asset_reference.py","lineNumber":97,"sourceCode":"    reference_id: str,\n) -> AssetReference | None:\n    return session.get(AssetReference, reference_id)\n\n\ndef get_reference_with_owner_check(\n    session: Session,\n    reference_id: str,\n    owner_id: str,\n) -> AssetReference:\n    \"\"\"Fetch a reference and verify ownership.\n\n    Raises:\n        ValueError: if reference not found or soft-deleted\n        PermissionError: if owner_id doesn't match\n    \"\"\"\n    ref = get_reference_by_id(session, reference_id=reference_id)\n    if not ref or ref.deleted_at is not None:\n        raise ValueError(f\"AssetReference {reference_id} not found\")\n    if ref.owner_id and ref.owner_id != owner_id:\n        raise PermissionError(\"not owner\")\n    return ref\n\n\ndef get_reference_by_file_path(\n    session: Session,\n    file_path: str,\n) -> AssetReference | None:\n    \"\"\"Get a reference by its file path.\"\"\"\n    return (\n        session.execute(\n            select(AssetReference).where(AssetReference.file_path == file_path).limit(1)\n        )\n        .scalars()\n        .first()\n    )\n","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/app/assets/database/queries/asset_reference.py#L79-L115","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nref = get_reference_and_verify_owner(session, reference_id=rid, owner_id=uid)\n\n// after\nfrom app.assets.database.queries.asset_reference import get_reference_by_id\nrow = get_reference_by_id(session, reference_id=rid)\nif not row or row.deleted_at is not None:\n    # treat as 404: refresh IDs or skip\n    return None\nref = get_reference_and_verify_owner(session, reference_id=rid, owner_id=uid)","handlingStrategy":"validation","validationCode":"from app.assets.database.queries.asset_reference import get_reference_by_id\n\ndef reference_is_live(session, reference_id: str) -> bool:\n    row = get_reference_by_id(session, reference_id=reference_id)\n    return row is not None and row.deleted_at is None","typeGuard":null,"tryCatchPattern":"try:\n    ref = get_reference_and_verify_owner(session, reference_id=rid, owner_id=uid)\nexcept ValueError as e:\n    # 404 ASSET_NOT_FOUND\n    ...\nexcept PermissionError:\n    # 403 FORBIDDEN\n    ...","preventionTips":["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."],"tags":["database","assets","not-found","soft-delete"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}