bytedance/deer-flow · error · HTTPException
Authentication required
Error message
Authentication required
What it means
401 Unauthorized from the channel-connections router's helper _get_user_id (channel_connections.py:142): request.state.user is None, meaning no authenticated user was resolved for the request. The channel connection API is user-scoped (every connection binds to an owner), so an anonymous request cannot proceed. It typically indicates the auth middleware did not run/populate state — the route's normal auth dependency should have rejected the request earlier.
Source
Thrown at backend/app/gateway/routers/channel_connections.py:142
),
}
_RUNTIME_REQUIREMENTS: dict[str, tuple[str, ...]] = {
"telegram": ("bot_token",),
"slack": ("bot_token", "app_token"),
"discord": ("bot_token",),
"feishu": ("app_id", "app_secret"),
"dingtalk": ("client_id", "client_secret"),
"wechat": ("bot_token",),
"wecom": ("bot_id", "bot_secret"),
"buzz": ("relay_url", "private_key"),
}
def _get_user_id(request: Request) -> str:
user = getattr(request.state, "user", None)
if user is None:
raise HTTPException(status_code=401, detail="Authentication required")
return str(user.id)
def _get_app_config():
from deerflow.config.app_config import get_app_config
return get_app_config()
async def _get_runtime_config_store(request: Request) -> ChannelRuntimeConfigStore:
store = getattr(request.app.state, "channel_runtime_config_store", None)
if isinstance(store, ChannelRuntimeConfigStore):
return store
# Constructing the store reads its JSON file from disk; keep it off the
# event loop.
store = await asyncio.to_thread(ChannelRuntimeConfigStore)
request.app.state.channel_runtime_config_store = store
return storeView on GitHub (pinned to 1dd6ba1acb)
Solutions
- Authenticate first: obtain a session (login) or valid token and send it with the request (cookie or Authorization header, per the Gateway auth scheme)
- If this appears in tests, ensure the test client sets up request.state.user or uses the app's auth fixtures rather than hitting the router function bare
- Verify the channel-connections router is mounted with its auth dependency intact (not include_router(..., dependencies=[]) overrides)
Example fix
# before curl -X GET http://localhost:2026/api/channels/connections # -> 401 Authentication required # after TOKEN=$(curl -s -X POST http://localhost:2026/api/auth/login -d 'username=...&password=...' | jq -r .access_token) curl -H "Authorization: Bearer $TOKEN" http://localhost:2026/api/channels/connections
Defensive patterns
Strategy: validation
Validate before calling
const resp = await fetch("/api/channels/connections");
if (resp.status === 401) { await redirectToLogin(); return; }
const data = await resp.json(); Try / catch
try { await listConnections() } catch (e) { if (e.status === 401) { await reauthenticate(); retryOnce(); } else throw e; } Prevention
- Attach credentials (cookie/Authorization) to every channel-connections call
- Handle 401 by refreshing the session once, then retrying exactly once
- Don't disable the router's auth dependency when mounting — request.state.user must be populated
When it happens
Trigger: Calling /api/channels/connections/* endpoints without a valid session/JWT (or with an expired token) in a context where the router-level auth dependency was bypassed — e.g. direct internal invocation, misconfigured middleware ordering, or a token that failed cookie/bearer resolution.
Common situations: Scripting the channel-connection endpoints with a missing/expired access token; auth disabled mode where routes are mounted but state.user is never set; middleware chain reordered so channel routes mount before auth wiring.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/d17c1010c500cb4e.
Report an issue: GitHub.