bytedance/deer-flow · error · HTTPException

{detail}

Error message

{detail}

What it means

HTTP 403 raised by require_admin_user() when the authenticated caller's system_role is not 'admin'. The dependency first prefers request.state.user stamped by AuthMiddleware, falling back to get_current_user_from_request(); the detail string is supplied per-route by the caller, so the message varies by endpoint.

Source

Thrown at backend/app/gateway/deps.py:804

    """Require the authenticated caller to be an admin user.

    ``AuthMiddleware`` normally stamps ``request.state.user`` before the request
    reaches a router. Falling back to the strict dependency keeps the route safe
    in tests or alternative ASGI compositions that mount a router without the
    global middleware. ``detail`` is the route-specific 403 message.

    Centralising this here means a future change to the admin definition (e.g.
    allowing an internal system role, adding audit logging, or switching to a
    permission-based check) lands in one place instead of drifting across the
    per-router copies that previously existed in ``mcp``, ``channel_connections``
    and ``channels``.
    """
    user = getattr(request.state, "user", None)
    if user is None:
        user = await get_current_user_from_request(request)

    if getattr(user, "system_role", None) != "admin":
        raise HTTPException(status_code=403, detail=detail)


async def get_optional_user_from_request(request: Request):
    """Get optional authenticated user from request.

    Returns None if not authenticated.
    """
    try:
        return await get_current_user_from_request(request)
    except HTTPException:
        return None


async def get_current_user(request: Request) -> str | None:
    """Extract user_id from request cookie, or None if not authenticated.

    Thin adapter that returns the string id for callers that only need
    identification (e.g., ``feedback.py``). Full-user callers should use

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Verify the caller's system_role in the users store; promote the intended account (UPDATE users SET system_role='admin' or the admin management endpoint)
  2. Log in as an actual admin user for admin operations
  3. If the request should have been stamped by AuthMiddleware with an internal admin identity, confirm the middleware ordering and that the internal auth source is enabled for that path
  4. In tests, use the admin user fixture
Defensive patterns

Strategy: validation

Validate before calling

// before calling admin APIs
const me = await api.get('/api/auth/me');
if (me.system_role !== 'admin') throw new Error('admin only');

Type guard

type IsAdmin = (u: { system_role?: string } | null) => boolean;
const isAdmin: IsAdmin = (u) => u?.system_role === 'admin';

Try / catch

try {
    await api.post('/api/admin/extensions/enable', body)
except HTTPError as e:
    if e.status == 403:
        raise PermissionError('Admin role required for this operation')
    raise

Prevention

When it happens

Trigger: Calling an admin-only route (extension management in mcp/channels/channel_connections routers, admin config endpoints) as a regular user or with a token whose user record lacks system_role='admin'.

Common situations: Default first-registered user is not admin and tries admin endpoints; user record edited/seeded without the admin role; internal/system service account (not an admin user) hitting an admin route; tests using a standard user fixture for admin flows.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/77e8da38befa28ab. Report an issue: GitHub.