{"record":{"id":"cbdccddb7d2a67d8","repo":"Comfy-Org/ComfyUI","slug":"forbidden","errorCode":"FORBIDDEN","errorMessage":"not owner","messagePattern":"not owner","errorType":"exception","errorClass":"PermissionError","httpStatus":403,"severity":"error","filePath":"app/assets/database/queries/asset_reference.py","lineNumber":99,"sourceCode":"    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\n\ndef count_active_siblings(","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/app/assets/database/queries/asset_reference.py#L81-L117","documentation":"PermissionError raised by the ownership-verified reference fetch when the reference row has a non-empty owner_id that does not match the caller-supplied owner_id. Empty owner_id on the row is treated as unowned and allowed, so the guard only rejects genuine mismatches between two different owners.","triggerScenarios":"Passing an owner_id different from the reference's ref.owner_id when ref.owner_id is set (non-empty string). Happens on any owner-scoped read/update/delete of another user's reference.","commonSituations":"Multi-user deployments where references are created by different accounts; a client sending an empty, default, or stale owner/user identifier; tests that create references without an owner and later fetch them with an owner_id set (this passes only because owner_id on the row is empty); mixing up authenticated user IDs between services.","solutions":["Pass the owner_id that was recorded when the reference was created (the creating user's ID).","If the reference is intentionally shared, clear/empty its owner_id in the database so the ownership check is skipped.","If you administer the system, look up ref.owner_id directly and confirm which account owns the asset.","Catch PermissionError at the API layer and map it to 403 rather than letting it surface as a 500."],"exampleFix":"// before\nref = get_reference_and_verify_owner(session, reference_id=rid, owner_id=current_uid)\n\n// after\ntry:\n    ref = get_reference_and_verify_owner(session, reference_id=rid, owner_id=current_uid)\nexcept PermissionError:\n    raise HTTPException(status_code=403, detail=\"not owner\")","handlingStrategy":"try-catch","validationCode":"ref = get_reference_by_id(session, reference_id=rid)\nif ref is not None and ref.owner_id and ref.owner_id != caller_owner_id:\n    # reject before calling the verified fetch\n    raise HTTPException(status_code=403, detail=\"not owner\")","typeGuard":null,"tryCatchPattern":"try:\n    ref = get_reference_and_verify_owner(session, reference_id=rid, owner_id=uid)\nexcept PermissionError:\n    raise HTTPException(status_code=403, detail=\"not owner\")\nexcept ValueError:\n    raise HTTPException(status_code=404, detail=\"reference not found\")","preventionTips":["Propagate the authenticated user's ID as owner_id on every owner-scoped call; never default it ad hoc.","Remember rows with empty owner_id are unowned and always pass the check.","Separate the 403 (PermissionError) path from the 404 (ValueError) path in handlers."],"tags":["permissions","assets","multi-user","authorization"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}