langflow-ai/langflow · warning · HTTPException

str(e)

Error message

str(e)

What it means

HTTP 400 from _create_flow's catch-all: the raised exception has an `errors` attribute — the signature of a Pydantic ValidationError (raised by Flow.model_validate / FlowRead.model_validate / field coercion inside creation). The exception's str() (which includes per-field error details) becomes the response detail, and genuine HTTPExceptions are re-raised before this branch.

Source

Thrown at src/backend/base/langflow/api/v1/flows_helpers.py:350

        # Apply the stable ID: explicit flow_id param (PUT upsert) takes precedence,
        # then flow.id (stable import from FlowCreate), then the uuid4 default.
        effective_id = flow_id if flow_id is not None else flow.id
        if effective_id is not None:
            db_flow.id = effective_id

        db_flow.updated_at = datetime.now(timezone.utc)
        await _validate_and_assign_folder(session, db_flow, user_id)

        session.add(db_flow)
        await session.flush()
        await session.refresh(db_flow)
        await _save_flow_to_fs(db_flow, user_id, storage_service)

        return FlowRead.model_validate(db_flow, from_attributes=True)
    except Exception as e:
        if hasattr(e, "errors"):
            raise HTTPException(status_code=400, detail=str(e)) from e
        if isinstance(e, HTTPException):
            raise
        logger.exception("Error creating flow")
        raise HTTPException(status_code=500, detail="An internal error occurred while creating the flow.") from e


async def _read_flow(
    session: AsyncSession,
    flow_id: UUID,
    user_id: UUID,
):
    """Read a flow.

    When the registered authorization service supports cross-user fetch
    (authorization plugin), the row is loaded by id alone and the caller's
    ``ensure_flow_permission`` decides access. Otherwise the query stays
    owner-scoped so the OSS pass-through default cannot widen visibility.
    """

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Read the response detail: str(ValidationError) lists each failing field and reason — fix those fields.
  2. Validate the payload client-side against the FlowCreate schema before posting.
  3. If the error names a field you never sent, suspect server-side model coercion and check version mismatch between client schema and server.

Example fix

# before
{"name": "f", "data": [1, 2]}          # data must be a dict
# after
{"name": "f", "data": {"nodes": [], "edges": []}}
Defensive patterns

Strategy: validation

Validate before calling

if (typeof body.data !== 'object' || body.data === null || Array.isArray(body.data)) throw new Error('flow.data must be a dict');

Type guard

const isFlowData = (d: unknown): d is {nodes: unknown[]; edges: unknown[]} => typeof d === 'object' && d !== null && !Array.isArray(d) && 'nodes' in d && 'edges' in d;

Try / catch

try { await createFlow(body) } catch (e) { if (e.status === 400 && e.detail.includes('validation')) showFieldErrors(e.detail); throw e; }

Prevention

When it happens

Trigger: POST /api/v1/flows (or import/upsert paths calling _create_flow) with a payload that fails Pydantic validation during ORM->model conversion or field assignment — wrong types for flow.data, invalid datetime on updated_at handling, or a field constraint violated that request schema validation did not catch.

Common situations: data is a list or string instead of a dict; timestamps serialized in a non-ISO format; enum fields (e.g. flow style/visibility) given unknown values; sending null for a required field that the request model marks optional but the ORM model does not.

Related errors


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