bytedance/deer-flow · error · HTTPException
CSRF token missing. Include X-CSRF-Token header.
Error message
CSRF token missing. Include X-CSRF-Token header.
What it means
HTTP 403 from the LangGraph-compatible runtime's CSRF guard: for state-changing methods (POST, PUT, DELETE, PATCH), when auth is enabled, the request must carry BOTH a csrf_token cookie and an X-CSRF-Token header. Missing either raises 'CSRF token missing. Include X-CSRF-Token header.' This is double-submit-cookie CSRF protection on the proxied /api/langgraph/* surface.
Source
Thrown at backend/app/gateway/langgraph_auth.py:49
def _check_csrf(request) -> None:
"""Enforce Double Submit Cookie CSRF check for state-changing requests.
Mirrors Gateway's CSRFMiddleware logic so that LangGraph routes
proxied directly by nginx have the same CSRF protection.
"""
method = getattr(request, "method", "") or ""
if method.upper() not in _CSRF_METHODS:
return
if is_auth_disabled():
return
cookie_token = request.cookies.get("csrf_token")
header_token = request.headers.get("x-csrf-token")
if not cookie_token or not header_token:
raise Auth.exceptions.HTTPException(
status_code=403,
detail="CSRF token missing. Include X-CSRF-Token header.",
)
if not secrets.compare_digest(cookie_token, header_token):
raise Auth.exceptions.HTTPException(
status_code=403,
detail="CSRF token mismatch.",
)
@auth.authenticate
async def authenticate(request):
"""Validate the session cookie, decode JWT, and check token_version.
Same validation chain as Gateway's get_current_user_from_request:
cookie → decode JWT → DB lookup → token_version match
Also enforces CSRF on state-changing methods.View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Read csrf_token from the login response cookies and send it back on every mutating call: header 'X-CSRF-Token: <value>' with credentials included
- In browser code use a shared fetch wrapper that attaches the header from document.cookie for POST/PUT/DELETE/PATCH
- For curl: curl -b jar -c jar -H "X-CSRF-Token: $(awk '/csrf_token/{print $7}' jar)" ...
- Ensure CORS config (if cross-origin) allows the X-CSRF-Token request header
Example fix
// before: 403 CSRF token missing
await fetch('/api/langgraph/threads', {
method: 'POST', credentials: 'include',
headers: { 'content-type': 'application/json' }, body: '{}',
});
// after
const csrf = document.cookie.match(/csrf_token=([^;]+)/)?.[1];
await fetch('/api/langgraph/threads', {
method: 'POST', credentials: 'include',
headers: { 'content-type': 'application/json', 'X-CSRF-Token': csrf }, body: '{}',
}); Defensive patterns
Strategy: validation
Validate before calling
function csrfToken(): string | null {
const m = document.cookie.match(/(?:^|; )csrf_token=([^;]+)/);
return m ? decodeURIComponent(m[1]) : null;
}
// guard before any mutation
const t = csrfToken();
if (!t) throw new Error('no csrf cookie — login first');
fetch(url, { method: 'POST', credentials: 'include', headers: { 'X-CSRF-Token': t } }); Type guard
null
Try / catch
catch (e) {
if (e.status === 403 && e.detail?.includes('CSRF token missing')) {
await refreshSession(); // obtain csrf cookie, then replay once
return fetchOnce(url, opts);
}
throw e;
} Prevention
- Route every mutating call through one client wrapper that injects X-CSRF-Token from the cookie
- Login response handler must persist the csrf_token cookie before any POST
- Only POST/PUT/DELETE/PATCH need the header — leave GETs clean
- If auth is disabled in your env, the guard is skipped — don't build clients that rely on that
When it happens
Trigger: POST/PUT/DELETE/PATCH to any LangGraph-runtime route (e.g. runs/threads mutations through nginx /api/langgraph/) without the X-CSRF-Token header, without the csrf_token cookie, or both — typically a non-browser client or a fetch that forwards cookies but not custom headers.
Common situations: Script/curl client that authenticates with cookies but never reads the Set-Cookie csrf_token to echo it in a header; frontend fetch omitting the X-CSRF-Token header after a refactor; CORS preflight stripping the custom header; auth disabled flag turned off (enabled auth) in an environment where the client was built assuming no CSRF.
Related errors
- CSRF token mismatch.
- Not authenticated
- Failed to load agents: ${res.statusText}
- request_failed
- Your email could not be verified by the identity provider. P
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/12a10b85ab6b921f.
Report an issue: GitHub.