langflow-ai/langflow · warning · HTTPException

Unknown permission_level {payload.permission_level!r}

Error message

Unknown permission_level {payload.permission_level!r}

What it means

Raised by PATCH /api/v1/authz/shares/{share_id} when payload.permission_level is not a valid SharePermissionLevel enum member. The route validates by constructing SharePermissionLevel(value) before touching the DB, so a ValueError becomes a 400 with the bad value echoed — an early, clear rejection ahead of the DB CHECK constraint.

Source

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

        session,
        resource_type=row.resource_type,
        resource_id=row.resource_id,
    )
    await _ensure_can_administer_share(user=current_user, owner_id=owner_id)
    # See create_share: owner_id is the *resource* owner so non-owners are
    # forced through ensure_share_permission's plugin enforce() path.
    await ensure_share_permission(
        current_user,
        ShareAction.UPDATE,
        share_id=share_id,
        share_user_id=owner_id,
    )

    # Validate permission_level (422 before DB CHECK).
    try:
        row.permission_level = SharePermissionLevel(payload.permission_level).value
    except ValueError as exc:
        raise HTTPException(
            status_code=400,
            detail=f"Unknown permission_level {payload.permission_level!r}",
        ) from exc
    session.add(row)
    # Rollback + fixed 409 on constraint failure (same as create_share).
    try:
        await session.flush()
    except Exception as exc:
        await session.rollback()
        logger.warning("authz_share update rejected: %s", exc)
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail="Share could not be updated: it may conflict with an existing share.",
        ) from exc
    await session.refresh(row)
    response = (await _serialize_shares(session, [row]))[0]
    await session.commit()

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Use only permission_level values from the API's OpenAPI schema (SharePermissionLevel enum)
  2. Restrict the client to a dropdown sourced from /openapi.json instead of free text
  3. If the level came from an older API version, map it to the current enum before sending

Example fix

// before
await updateShare(id, { permission_level: 'writer' });

// after
await updateShare(id, { permission_level: 'write' }); // per SharePermissionLevel enum
Defensive patterns

Strategy: type-guard

Validate before calling

const PERMISSION_LEVELS = ['read', 'write']; // mirror SharePermissionLevel from /openapi.json
if (!PERMISSION_LEVELS.includes(permission_level)) {
  throw new Error(`invalid permission_level ${permission_level}`);
}

Type guard

type SharePermissionLevel = 'read' | 'write';
const isPermissionLevel = (v: unknown): v is SharePermissionLevel =>
  v === 'read' || v === 'write';

Prevention

When it happens

Trigger: PATCH /authz/shares/{id} with {"permission_level": "owner"} or "rw" or any string not in the SharePermissionLevel members (e.g. valid ones like read/write style levels defined by the enum).

Common situations: Client hardcoded strings drifting from the enum after a Langflow upgrade; copy-pasting levels from other systems (Google-style 'writer' vs this API's levels); sending numeric levels to a string enum.

Related errors


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