langflow-ai/langflow · error · ValueError

flow_version_id must be provided as a UUID string or UUID ob

Error message

flow_version_id must be provided as a UUID string or UUID object.

What it means

Pydantic field validator (mode='before') on WatsonxApiCreatedTool.flow_version_id rejects values that are neither a UUID instance nor a string. The Watsonx Orchestrate deployment mapper requires the Langflow flow version id as a UUID, and any non-string type (int, None, dict, list) fails before Pydantic's own UUID coercion runs. The error surfaces as a pydantic ValidationError wrapped in the mapper's payload-shaping response.

Source

Thrown at src/backend/base/langflow/api/v1/mappers/deployments/watsonx_orchestrate/payloads.py:420

        raise ValueError(msg)


class WatsonxApiCreatedTool(BaseModel):
    """API response shape for a tool created from a Langflow flow version."""

    model_config = {"extra": "forbid"}

    flow_version_id: UUID
    tool_id: NonEmptyString = Field(description="Provider-owned tool identifier.")

    @field_validator("flow_version_id", mode="before")
    @classmethod
    def normalize_flow_version_id(cls, value: Any) -> UUID:
        if isinstance(value, UUID):
            return value
        if not isinstance(value, str):
            msg = "flow_version_id must be provided as a UUID string or UUID object."
            raise ValueError(msg)  # noqa: TRY004
        try:
            return UUID(value)
        except ValueError as exc:
            msg = "flow_version_id must be a valid UUID."
            raise ValueError(msg) from exc


class WatsonxApiDeploymentCreateResultData(BaseModel):
    """Provider-result payload used by Watsonx mapper create shapers."""

    model_config = {"extra": "ignore"}

    name: NonEmptyString = Field(description="Provider technical agent name.")
    display_name: NonEmptyString
    created_app_ids: list[NonEmptyString] = Field(default_factory=list)
    created_tools: list[WatsonxApiCreatedTool] = Field(default_factory=list)

    @classmethod

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Pass flow_version_id as a canonical UUID string, e.g. str(flow_version.id) or str(uuid4()).
  2. If the value comes from another API/DB, coerce with str(value) before building the payload.
  3. Ensure the upstream step that creates the flow version actually ran and returned an id (not None).
  4. If you already have a uuid.UUID object, pass it directly — the validator accepts UUID instances.

Example fix

# before
created_tool = {"tool_id": "my-tool", "flow_version_id": 12345}

# after
from uuid import UUID
created_tool = {"tool_id": "my-tool", "flow_version_id": "550e8400-e29b-41d4-a716-446655440000"}
# or: "flow_version_id": flow_version.id  (uuid.UUID instance)
Defensive patterns

Strategy: type-guard

Validate before calling

from uuid import UUID

def ok_flow_version_id(v) -> bool:
    return isinstance(v, (UUID, str)) and v is not None

Type guard

from uuid import UUID
from typing import Any

def is_flow_version_id(v: Any) -> TypeGuard[UUID | str]:
    return isinstance(v, UUID) or isinstance(v, str)

Try / catch

Wrap the deployment-create call in try/except pydantic.ValidationError and inspect e.errors()[0]['msg'] to distinguish 'must be provided as' (wrong type) from 'must be a valid UUID' (bad string).

Prevention

When it happens

Trigger: POST/PUT to a Watsonx Orchestrate deployment endpoint whose created-tool payload passes flow_version_id as a non-string, e.g. {"flow_version_id": 12345}, null, or an object; also calling the mapper programmatically with a raw integer id read from a DB row or config.

Common situations: Scripts that read the version id from a source that yields ints (e.g. some DB drivers, JSON with numeric ids); passing the whole request body or a nested object instead of the id field; None leaking in when a flow version was never created upstream.

Related errors


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