{"record":{"id":"a6c267e907592ee7","repo":"langgenius/dify","slug":"must-be-a-valid-uuid","errorCode":null,"errorMessage":"must be a valid UUID","messagePattern":"must be a valid UUID","errorType":"validation","errorClass":"ValueError","httpStatus":400,"severity":"warning","filePath":"api/controllers/console/explore/completion.py","lineNumber":75,"sourceCode":"    query: str\n    files: list[dict[str, Any]] | None = Field(default=None)\n    conversation_id: str | None = None\n    parent_message_id: str | None = None\n    retriever_from: str = Field(default=\"explore_app\")\n\n    @field_validator(\"conversation_id\", \"parent_message_id\", mode=\"before\")\n    @classmethod\n    def normalize_uuid(cls, value: str | UUID | None) -> str | None:\n        \"\"\"\n        Accept blank IDs and validate UUID format when provided.\n        \"\"\"\n        if not value:\n            return None\n\n        try:\n            return helper.uuid_value(value)\n        except ValueError as exc:\n            raise ValueError(\"must be a valid UUID\") from exc\n\n\nregister_schema_models(console_ns, CompletionMessageExplorePayload, ChatMessagePayload)\nregister_response_schema_models(console_ns, SimpleResultResponse)\n\n\n# define completion api for user\n@console_ns.route(\n    \"/installed-apps/<uuid:installed_app_id>/completion-messages\",\n    endpoint=\"installed_app_completion\",\n)\nclass CompletionApi(InstalledAppResource):\n    @console_ns.expect(console_ns.models[CompletionMessageExplorePayload.__name__])\n    @console_ns.response(200, \"Success\")\n    @with_current_user\n    @with_session\n    @model_validate(CompletionMessageExplorePayload)\n    def post(","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/explore/completion.py#L57-L93","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Only pass a canonical UUID v4 string (or None/empty) for conversation_id and parent_message_id.","If you hold a non-UUID identifier, resolve it to the Dify UUID before calling, or omit the field to start a new conversation.","Validate the value client-side with a UUID regex before posting.","Ensure the value is not undefined/NaN serialized as the literal string 'undefined'."],"exampleFix":"// before\nbody.conversation_id = chatSession.nanoid; // e.g. 'V1StGXR8_Z5j' -> 422\n// after: resolve to the Dify UUID, or omit for a new conversation\nbody.conversation_id = chatSession.difyUuid; // '550e8400-e29b-41d4-a716-446655440000'\n// or\ndelete body.conversation_id; // start a new conversation","handlingStrategy":"validation","validationCode":"import { v4 as uuidv4, validate as uuidValidate } from \"uuid\"\n\nfunction normalizeId(value: string | null | undefined): string | null {\n  if (!value) return null\n  if (!uuidValidate(value)) throw new Error(`conversation_id must be a UUID, got ${value}`)\n  return value\n}\n// before POST:\nbody.conversation_id = normalizeId(body.conversation_id)\nbody.parent_message_id = normalizeId(body.parent_message_id)","typeGuard":"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\nfunction isUuid(value: unknown): value is string {\n  return typeof value === \"string\" && UUID_RE.test(value)\n}","tryCatchPattern":"try { await postChat(body) }\ncatch (e) {\n  if (e.status === 422 && /must be a valid UUID/.test(e.message))\n    showFieldError('conversation_id or parent_message_id must be a UUID or blank')\n  else throw e\n}","preventionTips":["Only pass canonical UUID strings (or null/empty) for conversation_id and parent_message_id.","Validate with a UUID regex client-side before posting.","Never send internal/nanoid identifiers in these fields; map them to the Dify UUID first, or omit to start a new conversation.","Guard against the literal string 'undefined' being serialized from the frontend."],"tags":["validation","uuid","pydantic","chat","http-422"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}