langflow-ai/langflow · error · HTTPException

Invalid flow_id: not a valid UUID.

Error message

Invalid flow_id: not a valid UUID.

What it means

Raised by the assistant runner's _ensure_flow when the supplied flow_id string cannot be parsed by the UUID constructor. The MCP assistant accepts an optional flow_id to target an existing flow; anything that is not a canonical UUID string (including UUIDs with braces, urn: prefix without normalization quirks, or plain garbage) is rejected with 422 before any DB access.

Source

Thrown at src/backend/base/langflow/agentic/utils/assistant_runner.py:41

from langflow.agentic.services.flow_types import LANGFLOW_ASSISTANT_FLOW
from langflow.api.v1.flows import _new_flow, _save_flow_to_fs
from langflow.initial_setup.setup import get_or_create_default_folder
from langflow.services.database.models.flow.guards import ensure_flow_unlocked, lock_flow_for_update
from langflow.services.database.models.flow.model import Flow, FlowCreate
from langflow.services.deps import get_storage_service

if TYPE_CHECKING:
    from sqlmodel.ext.asyncio.session import AsyncSession

DEFAULT_FLOW_NAME = "Assistant Flow"


async def _ensure_flow(session: AsyncSession, user_id: UUID, flow_id: str | None) -> tuple[Flow, bool]:
    if flow_id:
        try:
            flow_uuid = UUID(flow_id)
        except ValueError as exc:
            raise HTTPException(status_code=422, detail="Invalid flow_id: not a valid UUID.") from exc
        flow = await session.get(Flow, flow_uuid)
        if flow is None or (flow.user_id is not None and str(flow.user_id) != str(user_id)):
            raise HTTPException(status_code=404, detail="Flow not found.")
        return flow, False

    folder = await get_or_create_default_folder(session, user_id)
    new_flow = FlowCreate(
        name=DEFAULT_FLOW_NAME,
        description="Created by the Langflow Assistant via MCP",
        data={"nodes": [], "edges": []},
        folder_id=folder.id,
        user_id=user_id,
    )
    storage_service = get_storage_service()
    created = await _new_flow(session=session, flow=new_flow, user_id=user_id, storage_service=storage_service)
    await session.commit()
    # _new_flow returns a FlowRead; re-fetch the ORM row so later edits persist.
    db_flow = await session.get(Flow, created.id)

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Use the flow's UUID as shown in the URL /api/v1/flows/{id} — copy it verbatim, no braces or prefixes.
  2. If you only know the name, first resolve it via GET /api/v1/flows/?name=... and use the returned id.
  3. Strip whitespace and validate the value client-side with a UUID regex before calling.

Example fix

# before
await run_assistant(flow_id="Assistant Flow", ...)

# after
flows = await client.get("/api/v1/flows/", params={"name": "Assistant Flow"})
await run_assistant(flow_id=flows[0]["id"], ...)
Defensive patterns

Strategy: validation

Validate before calling

from uuid import UUID

def is_flow_uuid(value: str) -> bool:
    try:
        UUID(value.strip())
        return True
    except (ValueError, AttributeError):
        return False

Type guard

def is_uuid_string(v: str | None) -> TypeGuard[str]:
    if not isinstance(v, str):
        return False
    try:
        UUID(v.strip())
        return True
    except ValueError:
        return False

Prevention

When it happens

Trigger: Calling the assistant run/edit endpoint or MCP tool with flow_id like 'my-flow', '123', a flow name, or a URL fragment instead of the flow's UUID; passing an int id from an external system.

Common situations: Confusing the flow's display name or endpoint name with its id; copying the id with surrounding quotes/whitespace from the UI URL; integrations storing their own numeric primary keys.

Related errors


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