{"record":{"id":"aba14311337c6deb","repo":"langgenius/dify","slug":"conversation-completed-aba143","errorCode":"conversation_completed","errorMessage":"The conversation has ended. Please start a new conversation.","messagePattern":"The conversation has ended\\. Please start a new conversation\\.","errorType":"console","errorClass":"ConversationCompletedError","httpStatus":400,"severity":"warning","filePath":"api/controllers/console/explore/completion.py","lineNumber":129,"sourceCode":"        installed_app.last_used_at = naive_utc_now()\n        db.session.commit()\n\n        try:\n            response = AppGenerateService.generate(\n                session=session,\n                app_model=app_model,\n                user=current_user,\n                args=args,\n                invoke_from=InvokeFrom.EXPLORE,\n                streaming=streaming,\n            )\n\n            # response-contract:ignore compact_generate_response\n            return helper.compact_generate_response(response)\n        except services.errors.conversation.ConversationNotExistsError:\n            raise NotFound(\"Conversation Not Exists.\")\n        except services.errors.conversation.ConversationCompletedError:\n            raise ConversationCompletedError()\n        except services.errors.app_model_config.AppModelConfigBrokenError:\n            logger.exception(\"App model config broken.\")\n            raise AppUnavailableError()\n        except ProviderTokenNotInitError as ex:\n            raise ProviderNotInitializeError(ex.description)\n        except QuotaExceededError:\n            raise ProviderQuotaExceededError()\n        except ModelCurrentlyNotSupportError:\n            raise ProviderModelCurrentlyNotSupportError()\n        except InvokeError as e:\n            raise CompletionRequestError(e.description)\n        except ValueError as e:\n            raise e\n        except Exception:\n            logger.exception(\"internal server error.\")\n            raise InternalServerError()\n\n","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/explore/completion.py#L111-L147","documentation":"Raised by CompletionApi.post (HTTP 400, error_code 'conversation_completed') when AppGenerateService.generate raises services.errors.conversation.ConversationCompletedError. The targeted conversation has been explicitly ended/completed and will no longer accept new messages. This is a domain-level lifecycle guard from the conversation service, re-thrown here as an HTTP error.","triggerScenarios":"POST /console/installed-apps/<id>/completion-messages carrying args that reference a conversation already marked completed. The shared generate pipeline detects the conversation's completed state and aborts before invoking the model.","commonSituations":"Client continues to send to a conversation the server already closed (timeout, explicit stop, or completion); a long-lived client did not refresh after the conversation ended; completion app was wired to a conversation that a background job closed.","solutions":["Start a brand-new completion request without the completed conversation reference.","On the client, treat this error code as a signal to reset the conversation UI.","Review whether an explicit stop or a TTL policy closed the conversation.","If conversations should remain open, check the app's conversation lifecycle settings."],"exampleFix":"// before: reusing a conversation handle after completion\nif (err.code === 'conversation_completed') { retryWithSameConversation() }\n\n// after: start fresh when the server says the conversation ended\nif (err.code === 'conversation_completed') { startNewConversation() }","handlingStrategy":"try-catch","validationCode":"// For completion apps there is usually no conversation to check; if you carry one,\n// verify it is not completed before posting. Requires a conversation-status API if available.\n// Otherwise, the safest validation is simply to start a new completion without state.\nif (carriedConversationId) { /* completion apps are stateless — prefer not sending it */ }","typeGuard":"function isConversationUsable(conv) {\n  return Boolean(conv && conv.status !== 'completed' && conv.status !== 'ended');\n}","tryCatchPattern":"try {\n  await postCompletion(id, payload);\n} catch (err) {\n  if (err.code === 'conversation_completed') {\n    // reset state and start fresh; do not retry the same conversation\n    startNewCompletion();\n  } else { throw err; }\n}","preventionTips":["Treat 'conversation_completed' as terminal for that thread; never retry it.","Reset client-side conversation state whenever this code arrives.","Review app conversation lifecycle settings if completion is unexpected."],"tags":["explore","completion","conversation","lifecycle"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}