{"record":{"id":"37782d3c201b14a6","repo":"langflow-ai/langflow","slug":"not-found-37782d","errorCode":null,"errorMessage":"Not Found","messagePattern":"Not Found","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"src/backend/base/langflow/api/v1/a2a.py","lineNumber":96,"sourceCode":")\nfrom langflow.helpers.flow import get_flow_by_id_or_endpoint_name\nfrom langflow.helpers.user import get_user_by_flow_id_or_endpoint_name\nfrom langflow.services.database.models import A2ACheckpoint, A2ATask, Flow\nfrom langflow.services.database.models.api_key.crud import check_key\nfrom langflow.services.database.models.flow.model import FlowType\n\nrouter = APIRouter(prefix=\"/a2a\", tags=[\"a2a\"])\n\n\ndef _require_a2a_enabled() -> None:\n    \"\"\"Return 404 when the A2A feature flag is off.\n\n    Reads the live settings per request (after env/dotenv load), matching\n    langflow.api.v1.extensions._require_extension_reload_enabled.\n    \"\"\"\n    settings = get_settings_service().settings\n    if not getattr(settings, \"a2a_enabled\", False):\n        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=\"Not Found\")\n\n\nasync def _enforce_a2a_auth(flow: Flow, request: Request) -> None:\n    \"\"\"Enforce the folder's auth scheme before any dispatch, failing closed on the rest.\n\n    The flow always runs as its owner (see ``_run_flow``), so an unauthenticated run is a\n    run under the owner's identity. Gate by the folder's ``auth_type``:\n\n    - ``\"none\"`` / missing / no-folder -> public agent (the intended public A2A model).\n    - ``\"apikey\"`` / ``\"oauth\"`` -> require a valid langflow API key in ``x-api-key`` whose\n      owner is the flow owner. An oauth folder is fronted by an external OAuth broker (the dance\n      happens in front); the langflow transport itself still takes an owner-scoped api key,\n      exactly as the MCP transport does (``mcp_projects.verify_project_auth``), since credential\n      forwarding from the broker isn't available yet. Accepting another user's valid key would\n      let them trigger a run under the owner's identity, so scope to ``flow.user_id``.\n    - anything else (an auth type A2A doesn't understand) -> fail closed with 403: treating a\n      *protected* folder as public would expose an owner-identity run anonymously.\n","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/api/v1/a2a.py#L78-L114","documentation":"Raised by _require_a2a_enabled on every A2A router route (/.well-known agent card and /{flow_id}/jsonrpc) when the settings flag a2a_enabled is falsy. It reads live settings per request, so the 404 appears until the flag is set (env LANGFLOW_A2A_ENABLED or config) — regardless of whether the flow itself is A2A-capable. A 404 (not 403) is used so a disabled feature is indistinguishable from a non-existent route.","triggerScenarios":"GET /api/v1/a2a/... or POST /api/v1/a2a/{flow_id}/jsonrpc on a server started without LANGFLOW_A2A_ENABLED=true (or before .env load set it). Also mid-session after the flag was turned off, since settings are read per request.","commonSituations":"Deploying an A2A client against a default OSS install where the feature ships off; setting the env var only in one of several workers / docker-compose services; forgetting that the flag is read after dotenv load so a typo in the variable name silently keeps it disabled.","solutions":["Set LANGFLOW_A2A_ENABLED=true in the server environment (or .env) and restart","Verify the variable name/spelling and that the process actually sees it: print get_settings_service().settings.a2a_enabled in a shell or check the /settings endpoint","Ensure ALL workers/replicas have the flag, not just one container"],"exampleFix":"# before\ndocker compose up   # LANGFLOW_A2A_ENABLED unset\n# after\nLANGFLOW_A2A_ENABLED=true docker compose up","handlingStrategy":"validation","validationCode":"import httpx\n\ndef a2a_enabled(base_url: str) -> bool:\n    # cheapest probe: agent card for a known-agent flow returns 404 'Not Found' both when\n    # the flag is off and for unknown flows; a 200 on any agent flow proves the flag is on.\n    r = httpx.get(f\"{base_url}/api/v1/a2a/{AGENT_FLOW_ID}/card\")\n    return r.status_code != 404 or \"a2a_enabled\" in r.text  # refine per deployment","typeGuard":null,"tryCatchPattern":"try:\n    card = client.get_agent_card()\nexcept Exception as e:\n    if \"404\" in str(e) or \"Not Found\" in str(e):\n        raise ConfigError(\"LANGFLOW_A2A_ENABLED is off or flow not an a2a agent\") from e\n    raise","preventionTips":["Health-check A2A availability at deploy time before wiring clients","Set LANGFLOW_A2A_ENABLED in infrastructure-as-code so every worker gets it","Treat 404 on A2A routes as 'feature off or wrong flow' — check settings first"],"tags":["a2a","feature-flag","http-404","configuration"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}