langflow-ai/langflow · error · HTTPException

Share could not be created: it may already exist or conflict

Error message

Share could not be created: it may already exist or conflict with an existing share.

What it means

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.

Source

Thrown at src/backend/base/langflow/api/v1/authz_shares.py:246

    )

    row = AuthzShare(
        resource_type=payload.resource_type,
        resource_id=payload.resource_id,
        scope=payload.scope,
        target_id=payload.target_id,
        permission_level=payload.permission_level,
        created_by=current_user.id,
        created_at=datetime.now(timezone.utc),
    )
    session.add(row)
    try:
        await session.flush()
    except Exception as exc:
        # Log server-side; return a fixed 409 message (no schema leakage).
        await session.rollback()
        logger.warning("authz_share insert rejected: %s", exc)
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail="Share could not be created: it may already exist or conflict with an existing share.",
        ) from exc
    await session.refresh(row)
    response = (await _serialize_shares(session, [row]))[0]
    await session.commit()

    # Refresh policy after commit so plugins using a separate DB connection see
    # the durable authz_share row instead of the pre-commit transaction state.
    await _refresh_policy_for_share(payload.scope, payload.target_id, op="share:create")

    await audit_decision(
        user_id=current_user.id,
        action="share:create",
        obj=f"{payload.resource_type}:{payload.resource_id}",
        result="allow",
        details={
            "share_id": str(response.id),

View on GitHub (pinned to 976ec789d2)

Solutions

  1. GET /api/v1/authz/shares?resource_id=...&target_id=... first — if a share exists, PATCH its permission_level instead of creating a new one
  2. Guard submit buttons against double-fire and make create-or-update idempotent on the client
  3. On 409, re-list shares and reconcile rather than blind-retrying the POST

Example fix

// before
await createShare({ resource_type, resource_id, scope, target_id, permission_level });

// after
const existing = (await listShares({ resource_id, target_id })).find(s => s.scope === scope);
if (existing) {
  await updateShare(existing.id, { permission_level });
} else {
  await createShare({ resource_type, resource_id, scope, target_id, permission_level });
}
Defensive patterns

Strategy: validation

Validate before calling

async function upsertShare(params) {
  const existing = (await listShares({ resource_id: params.resource_id, target_id: params.target_id }))
    .find(s => s.scope === params.scope);
  if (existing) return updateShare(existing.id, { permission_level: params.permission_level });
  return createShare(params);
}

Try / catch

try {
  await createShare(params);
} catch (e) {
  if (e.status === 409) return upsertShare(params); // reconcile, don't blind-retry
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: Double-clicked 'Share' button; retry logic re-POSTing after a timeout when the first request actually succeeded; idempotency keys not implemented on the client.

Related errors


AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14). Data as JSON: /api/errors/4c2ff6f2df8b32ce. Report an issue: GitHub.