{"record":{"id":"f43ac51c1a271d98","repo":"langflow-ai/langflow","slug":"a2a-access-is-disabled-for-this-agent-unsupported","errorCode":null,"errorMessage":"A2A access is disabled for this agent: unsupported folder auth type {auth_type!r}.","messagePattern":"A2A access is disabled for this agent: unsupported folder auth type (.+?)\\.","errorType":"http","errorClass":"HTTPException","httpStatus":403,"severity":"error","filePath":"src/backend/base/langflow/api/v1/a2a.py","lineNumber":126,"sourceCode":"      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\n    Uses ``check_key`` directly, NOT ``api_key_security``: under AUTO_LOGIN the latter\n    returns the superuser for a *missing* key, which would silently bypass this gate.\n    \"\"\"\n    # Short writable session (check_key flushes usage counters), closed before\n    # dispatch so no lock is held across the up-to-300s run.\n    async with session_scope() as session:\n        auth_type = await folder_auth_type(flow, session)\n        if auth_type == \"none\":\n            return  # public agent\n        if auth_type not in (\"apikey\", \"oauth\"):\n            # Protected folder with a scheme A2A can't enforce: fail closed, never public.\n            raise HTTPException(\n                status_code=status.HTTP_403_FORBIDDEN,\n                detail=f\"A2A access is disabled for this agent: unsupported folder auth type {auth_type!r}.\",\n            )\n        api_key = request.headers.get(A2A_APIKEY_HEADER)\n        if not api_key:\n            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=\"API key required\")\n        user = await check_key(session, api_key)\n        # Same message for invalid and wrong-owner: don't reveal a key is valid for another user.\n        if user is None or user.id != flow.user_id:\n            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=\"Invalid API key\")\n\n\nclass _FlowContextBuilder(DefaultServerCallContextBuilder):\n    \"\"\"Carry the per-request flow_id into the shared executor via call-context state.\"\"\"\n\n    def build(self, request: Request) -> ServerCallContext:\n        context = super().build(request)\n        # Canonicalize to the same string form the resume guard uses (str(UUID(...))), so the durable","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/api/v1/a2a.py#L108-L144","documentation":"Raised by _enforce_a2a_auth when the flow lives in a folder whose auth_type is neither 'none', 'apikey', nor 'oauth' — e.g. a future/unknown scheme. A2A can only enforce owner-scoped API-key auth, so a protected folder with a scheme it cannot enforce fails closed with 403 instead of silently running the flow publicly. The flow always executes as its owner, so relaxing the gate would mean unauthenticated execution under the owner's identity.","triggerScenarios":"POST /api/v1/a2a/{flow_id}/jsonrpc for a flow whose folder has an auth_type value outside the supported set (custom/legacy auth scheme stored in the folder record).","commonSituations":"A plugin or manual DB edit introduced a new folder auth_type; upgrading Langflow where folder auth schemes changed; copying folder rows between environments with schema drift.","solutions":["Set the folder's auth_type to a supported value: 'none' (public agent), 'apikey', or 'oauth' (fronted by an external OAuth broker)","If you truly need the custom scheme, front the A2A endpoint with a proxy that enforces it and set the folder to 'none' with appropriate network controls","Report/patch the component that wrote the unsupported auth_type value"],"exampleFix":"-- before: folder row auth_type='saml'\n-- after: UPDATE folder SET auth_type='apikey' WHERE id='<folder-id>';","handlingStrategy":"validation","validationCode":"SUPPORTED_FOLDER_AUTH = {\"none\", \"apikey\", \"oauth\"}\n\ndef folder_auth_supported(auth_type: str | None) -> bool:\n    return (auth_type or \"none\") in SUPPORTED_FOLDER_AUTH","typeGuard":null,"tryCatchPattern":"try:\n    await client.send_message(flow_id, msg)\nexcept A2AClientError as e:\n    if \"unsupported folder auth type\" in str(e):\n        raise ConfigError(f\"Folder auth {extract_auth_type(str(e))!r} unsupported by A2A; switch to none/apikey/oauth\") from e\n    raise","preventionTips":["Restrict folder auth_type writes to the supported enum at the API/DB layer","Audit folder rows after upgrades for stray auth_type values","Document that custom auth schemes must be enforced in front of the A2A route, not behind it"],"tags":["a2a","auth","http-403","folder"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}