langflow-ai/langflow · error · HTTPException

Not Found

Error message

Not Found

What it means

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.

Source

Thrown at src/backend/base/langflow/api/v1/a2a.py:96

)
from langflow.helpers.flow import get_flow_by_id_or_endpoint_name
from langflow.helpers.user import get_user_by_flow_id_or_endpoint_name
from langflow.services.database.models import A2ACheckpoint, A2ATask, Flow
from langflow.services.database.models.api_key.crud import check_key
from langflow.services.database.models.flow.model import FlowType

router = APIRouter(prefix="/a2a", tags=["a2a"])


def _require_a2a_enabled() -> None:
    """Return 404 when the A2A feature flag is off.

    Reads the live settings per request (after env/dotenv load), matching
    langflow.api.v1.extensions._require_extension_reload_enabled.
    """
    settings = get_settings_service().settings
    if not getattr(settings, "a2a_enabled", False):
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Not Found")


async def _enforce_a2a_auth(flow: Flow, request: Request) -> None:
    """Enforce the folder's auth scheme before any dispatch, failing closed on the rest.

    The flow always runs as its owner (see ``_run_flow``), so an unauthenticated run is a
    run under the owner's identity. Gate by the folder's ``auth_type``:

    - ``"none"`` / missing / no-folder -> public agent (the intended public A2A model).
    - ``"apikey"`` / ``"oauth"`` -> require a valid langflow API key in ``x-api-key`` whose
      owner is the flow owner. An oauth folder is fronted by an external OAuth broker (the dance
      happens in front); the langflow transport itself still takes an owner-scoped api key,
      exactly as the MCP transport does (``mcp_projects.verify_project_auth``), since credential
      forwarding from the broker isn't available yet. Accepting another user's valid key would
      let them trigger a run under the owner's identity, so scope to ``flow.user_id``.
    - anything else (an auth type A2A doesn't understand) -> fail closed with 403: treating a
      *protected* folder as public would expose an owner-identity run anonymously.

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Set LANGFLOW_A2A_ENABLED=true in the server environment (or .env) and restart
  2. 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
  3. Ensure ALL workers/replicas have the flag, not just one container

Example fix

# before
docker compose up   # LANGFLOW_A2A_ENABLED unset
# after
LANGFLOW_A2A_ENABLED=true docker compose up
Defensive patterns

Strategy: validation

Validate before calling

import httpx

def a2a_enabled(base_url: str) -> bool:
    # cheapest probe: agent card for a known-agent flow returns 404 'Not Found' both when
    # the flag is off and for unknown flows; a 200 on any agent flow proves the flag is on.
    r = httpx.get(f"{base_url}/api/v1/a2a/{AGENT_FLOW_ID}/card")
    return r.status_code != 404 or "a2a_enabled" in r.text  # refine per deployment

Try / catch

try:
    card = client.get_agent_card()
except Exception as e:
    if "404" in str(e) or "Not Found" in str(e):
        raise ConfigError("LANGFLOW_A2A_ENABLED is off or flow not an a2a agent") from e
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14). Data as JSON: /api/errors/37782d3c201b14a6. Report an issue: GitHub.