langflow-ai/langflow · error · HTTPException
API key required
Error message
API key required
What it means
Raised by _enforce_a2a_auth when the flow's folder uses apikey/oauth auth but the JSON-RPC request carries no x-api-key header (A2A_APIKEY_HEADER). Because the flow runs as its owner, an unauthenticated run would be a run under the owner's identity, so the request is rejected with 401 before dispatch. Note it deliberately uses check_key, not api_key_security, to avoid AUTO_LOGIN silently substituting the superuser for a missing key.
Source
Thrown at src/backend/base/langflow/api/v1/a2a.py:132
Uses ``check_key`` directly, NOT ``api_key_security``: under AUTO_LOGIN the latter
returns the superuser for a *missing* key, which would silently bypass this gate.
"""
# Short writable session (check_key flushes usage counters), closed before
# dispatch so no lock is held across the up-to-300s run.
async with session_scope() as session:
auth_type = await folder_auth_type(flow, session)
if auth_type == "none":
return # public agent
if auth_type not in ("apikey", "oauth"):
# Protected folder with a scheme A2A can't enforce: fail closed, never public.
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail=f"A2A access is disabled for this agent: unsupported folder auth type {auth_type!r}.",
)
api_key = request.headers.get(A2A_APIKEY_HEADER)
if not api_key:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="API key required")
user = await check_key(session, api_key)
# Same message for invalid and wrong-owner: don't reveal a key is valid for another user.
if user is None or user.id != flow.user_id:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid API key")
class _FlowContextBuilder(DefaultServerCallContextBuilder):
"""Carry the per-request flow_id into the shared executor via call-context state."""
def build(self, request: Request) -> ServerCallContext:
context = super().build(request)
# Canonicalize to the same string form the resume guard uses (str(UUID(...))), so the durable
# store scope (_task_scope / _push_config_scope) and the checkpoint/resume guard agree even for
# a non-canonical UUID in the path (uppercase or hyphenless, both valid to the UUID route
# converter). Without this, the same task addressed via two encodings lands in two scopes.
context.state["flow_id"] = str(UUID(request.path_params["flow_id"]))
return context
View on GitHub (pinned to 976ec789d2)
Solutions
- Send the flow owner's Langflow API key in the x-api-key header on every JSON-RPC request
- Confirm the flow's folder auth_type — if it should be public, set the folder auth to 'none'
- Use the exact header name the card advertises (x-api-key), not Authorization: Bearer
Example fix
# before
client = Client(url) # no credentials
# after
client = Client(httpx_client=httpx.AsyncClient(headers={"x-api-key": OWNER_API_KEY})) Defensive patterns
Strategy: validation
Validate before calling
def has_owner_api_key configured() -> bool:
key = os.environ.get("FLOW_OWNER_API_KEY", "")
return bool(key) and len(key) >= 20 # cheap presence check, no network call Try / catch
try:
resp = await client.send_message(flow_id, payload)
except A2AClientError as e:
if "API key required" in str(e):
client = rebuild_client_with_x_api_key(os.environ["FLOW_OWNER_API_KEY"])
resp = await client.send_message(flow_id, payload)
else:
raise Prevention
- Configure the x-api-key header once in the shared httpx client, not per call
- Check the flow's folder auth_type before assuming the public path
- Name the env var after the owning account to avoid grabbing the wrong key
When it happens
Trigger: POST /api/v1/a2a/{flow_id}/jsonrpc (message/send, message/stream, etc.) to a flow in an apikey or oauth folder without an x-api-key header, e.g. a raw a2a-sdk client that only sets Authorization or no credentials at all.
Common situations: Testing the public-agent path against a flow that was later moved into an apikey folder; A2A clients that put credentials in a different header or a JSON-RPC field; assuming the agent card's security scheme is optional.
Related errors
- Invalid API key
- A2A access is disabled for this agent: unsupported folder au
- Incorrect username or password
- Invalid refresh token
- This project is configured for OAuth authentication, but the
AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14).
Data as JSON: /api/errors/533c2f1680472fb6.
Report an issue: GitHub.