langgenius/dify · warning · ValueError

must be a valid UUID

Error message

must be a valid UUID

What it means

Pydantic validation error 'must be a valid UUID', raised by the field_validator ChatMessagePayload.normalize_uuid on the conversation_id and parent_message_id fields (controllers/console/explore/completion.py:63-75). Blank/None values are accepted (returned as None). Any provided value is passed to libs.helper.uuid_value, which tries uuid.UUID(value); on failure it raises ValueError, which the validator re-raises as ValueError('must be a valid UUID'). Pydantic v2 converts this into a 422 Unprocessable Entity response before the handler runs.

Source

Thrown at api/controllers/console/explore/completion.py:75

    query: str
    files: list[dict[str, Any]] | None = Field(default=None)
    conversation_id: str | None = None
    parent_message_id: str | None = None
    retriever_from: str = Field(default="explore_app")

    @field_validator("conversation_id", "parent_message_id", mode="before")
    @classmethod
    def normalize_uuid(cls, value: str | UUID | None) -> str | None:
        """
        Accept blank IDs and validate UUID format when provided.
        """
        if not value:
            return None

        try:
            return helper.uuid_value(value)
        except ValueError as exc:
            raise ValueError("must be a valid UUID") from exc


register_schema_models(console_ns, CompletionMessageExplorePayload, ChatMessagePayload)
register_response_schema_models(console_ns, SimpleResultResponse)


# define completion api for user
@console_ns.route(
    "/installed-apps/<uuid:installed_app_id>/completion-messages",
    endpoint="installed_app_completion",
)
class CompletionApi(InstalledAppResource):
    @console_ns.expect(console_ns.models[CompletionMessageExplorePayload.__name__])
    @console_ns.response(200, "Success")
    @with_current_user
    @with_session
    @model_validate(CompletionMessageExplorePayload)
    def post(

View on GitHub (pinned to ef8544b173)

Solutions

  1. Only pass a canonical UUID v4 string (or None/empty) for conversation_id and parent_message_id.
  2. If you hold a non-UUID identifier, resolve it to the Dify UUID before calling, or omit the field to start a new conversation.
  3. Validate the value client-side with a UUID regex before posting.
  4. Ensure the value is not undefined/NaN serialized as the literal string 'undefined'.

Example fix

// before
body.conversation_id = chatSession.nanoid; // e.g. 'V1StGXR8_Z5j' -> 422
// after: resolve to the Dify UUID, or omit for a new conversation
body.conversation_id = chatSession.difyUuid; // '550e8400-e29b-41d4-a716-446655440000'
// or
delete body.conversation_id; // start a new conversation
Defensive patterns

Strategy: validation

Validate before calling

import { v4 as uuidv4, validate as uuidValidate } from "uuid"

function normalizeId(value: string | null | undefined): string | null {
  if (!value) return null
  if (!uuidValidate(value)) throw new Error(`conversation_id must be a UUID, got ${value}`)
  return value
}
// before POST:
body.conversation_id = normalizeId(body.conversation_id)
body.parent_message_id = normalizeId(body.parent_message_id)

Type guard

const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
function isUuid(value: unknown): value is string {
  return typeof value === "string" && UUID_RE.test(value)
}

Try / catch

try { await postChat(body) }
catch (e) {
  if (e.status === 422 && /must be a valid UUID/.test(e.message))
    showFieldError('conversation_id or parent_message_id must be a UUID or blank')
  else throw e
}

Prevention

When it happens

Trigger: POST to a chat-message endpoint that uses ChatMessagePayload (e.g. installed-app chat messages) with conversation_id or parent_message_id set to a non-UUID string such as 'abc', '123', a nanoid, an integer, or a malformed UUID like '550e8400-e29b-41d4-a716'. Blank strings and None are allowed and normalize to None.

Common situations: Client sends an internal/non-UUID id format (e.g., a sortable/nanoid from another system); copy-paste truncation of a UUID; frontend passes an empty-string sentinel that is not actually empty after trimming of surrounding characters (a truly empty string is fine); version mismatch where an older API accepted arbitrary strings.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/a6c267e907592ee7. Report an issue: GitHub.