{"record":{"id":"4c2ff6f2df8b32ce","repo":"langflow-ai/langflow","slug":"share-could-not-be-created-it-may-already-exist-o","errorCode":null,"errorMessage":"Share could not be created: it may already exist or conflict with an existing share.","messagePattern":"Share could not be created: it may already exist or conflict with an existing share\\.","errorType":"http","errorClass":"HTTPException","httpStatus":409,"severity":"error","filePath":"src/backend/base/langflow/api/v1/authz_shares.py","lineNumber":246,"sourceCode":"    )\n\n    row = AuthzShare(\n        resource_type=payload.resource_type,\n        resource_id=payload.resource_id,\n        scope=payload.scope,\n        target_id=payload.target_id,\n        permission_level=payload.permission_level,\n        created_by=current_user.id,\n        created_at=datetime.now(timezone.utc),\n    )\n    session.add(row)\n    try:\n        await session.flush()\n    except Exception as exc:\n        # Log server-side; return a fixed 409 message (no schema leakage).\n        await session.rollback()\n        logger.warning(\"authz_share insert rejected: %s\", exc)\n        raise HTTPException(\n            status_code=status.HTTP_409_CONFLICT,\n            detail=\"Share could not be created: it may already exist or conflict with an existing share.\",\n        ) from exc\n    await session.refresh(row)\n    response = (await _serialize_shares(session, [row]))[0]\n    await session.commit()\n\n    # Refresh policy after commit so plugins using a separate DB connection see\n    # the durable authz_share row instead of the pre-commit transaction state.\n    await _refresh_policy_for_share(payload.scope, payload.target_id, op=\"share:create\")\n\n    await audit_decision(\n        user_id=current_user.id,\n        action=\"share:create\",\n        obj=f\"{payload.resource_type}:{payload.resource_id}\",\n        result=\"allow\",\n        details={\n            \"share_id\": str(response.id),","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/api/v1/authz_shares.py#L228-L264","documentation":"Raised by POST /api/v1/authz/shares when session.flush() fails while inserting the authz_share row. The handler rolls back, logs the underlying exception server-side (logger.warning 'authz_share insert rejected'), and returns a fixed 409 so no DB schema details leak. Typical cause: the unique constraint on the share (same resource/scope/target) — the share already exists.","triggerScenarios":"POST /authz/shares twice with the same resource_type+resource_id+scope+target_id combination; concurrent requests creating the same share; a CHECK constraint rejection on the new row.","commonSituations":"Double-clicked 'Share' button; retry logic re-POSTing after a timeout when the first request actually succeeded; idempotency keys not implemented on the client.","solutions":["GET /api/v1/authz/shares?resource_id=...&target_id=... first — if a share exists, PATCH its permission_level instead of creating a new one","Guard submit buttons against double-fire and make create-or-update idempotent on the client","On 409, re-list shares and reconcile rather than blind-retrying the POST"],"exampleFix":"// before\nawait createShare({ resource_type, resource_id, scope, target_id, permission_level });\n\n// after\nconst existing = (await listShares({ resource_id, target_id })).find(s => s.scope === scope);\nif (existing) {\n  await updateShare(existing.id, { permission_level });\n} else {\n  await createShare({ resource_type, resource_id, scope, target_id, permission_level });\n}","handlingStrategy":"validation","validationCode":"async function upsertShare(params) {\n  const existing = (await listShares({ resource_id: params.resource_id, target_id: params.target_id }))\n    .find(s => s.scope === params.scope);\n  if (existing) return updateShare(existing.id, { permission_level: params.permission_level });\n  return createShare(params);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await createShare(params);\n} catch (e) {\n  if (e.status === 409) return upsertShare(params); // reconcile, don't blind-retry\n  throw e;\n}","preventionTips":["Disable submit buttons during in-flight share creation","Implement list-then-patch-or-create (upsert) semantics for shares"],"tags":["authz","api","shares","conflict","unique-constraint","create"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}