{"record":{"id":"c9d0c127fdf032dc","repo":"zylon-ai/private-gpt","slug":"stream-with-this-message-id-already-exists","errorCode":null,"errorMessage":"Stream with this message_id already exists","messagePattern":"Stream with this message_id already exists","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"private_gpt/server/chat_async/chat_async_service.py","lineNumber":34,"sourceCode":"\n@singleton\nclass ChatAsyncService:\n    @inject\n    def __init__(\n        self,\n        stream_manager: StreamManager,\n        chat_facade: ChatFacadeService,\n    ):\n        self.stream_manager = stream_manager\n        self._chat_facade = chat_facade\n\n    async def initiate_chat_stream(\n        self, request: ChatRequest, message_id: str | None = None\n    ) -> str:\n        \"\"\"Initiate a chat completion stream.\"\"\"\n        message_id = message_id or str(uuid4())\n        if message_id and await self.stream_manager.stream_exists(message_id):\n            raise ValueError(\"Stream with this message_id already exists\")\n\n        request = request.model_copy(\n            update={\n                \"context\": request.context.model_copy(\n                    update={\"correlation_id\": message_id}\n                )\n            }\n        )\n        event_generator = await self._chat_facade.create_chat_event_generator(\n            request=request\n        )\n        return await self.stream_manager.create_and_start_stream(\n            event_handler=StreamingEventHandler(),\n            stream_type=\"chat_completion\",\n            event_generator=event_generator,\n            correlation_id=message_id,\n            metadata={\n                \"message_count\": len(request.messages),","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/server/chat_async/chat_async_service.py#L16-L52","documentation":"Raised by ChatAsyncService.initiate_chat_stream when the provided message_id already identifies an existing stream in the StreamManager. Message IDs are correlation keys for async streams, so duplicates are rejected with a plain ValueError before a new stream is created.","triggerScenarios":"Calling POST /v1/messages/async (or initiate_chat_stream) with an explicit message_id that is already active or retained; retrying a timed-out request with the same client-generated id while the first stream still exists.","commonSituations":"Idempotency-style retries after network timeouts where the first request actually succeeded; clients reusing uuids from persistence; testing with hardcoded message ids.","solutions":["Let the server generate the id (omit message_id) unless you need idempotency.","On retry, first check stream_exists(message_id)/status endpoint; reuse or delete the existing stream before re-initiating.","Generate a fresh uuid4 per attempt if the previous stream was cancelled/deleted."],"exampleFix":"# before\nmsg_id = 'fixed-client-id'\nawait chat_service.initiate_chat_stream(request, message_id=msg_id)  # second call raises\n\n# after\nif await chat_service.stream_manager.stream_exists(msg_id):\n    await chat_service.stream_manager.clean_up_stream(msg_id)\nawait chat_service.initiate_chat_stream(request, message_id=msg_id)","handlingStrategy":"validation","validationCode":"if message_id and await stream_manager.stream_exists(message_id):\n    raise RuntimeError('id in use — pick another or clean up first')\nmessage_id = await chat_service.initiate_chat_stream(request, message_id=message_id)","typeGuard":null,"tryCatchPattern":"try:\n    await chat_service.initiate_chat_stream(request, message_id=msg_id)\nexcept ValueError:\n    meta = await client.get(f'/v1/messages/async/{msg_id}/status')\n    if meta.status_code == 404:\n        pass  # stale entry gone; safe to retry\n    # else reuse the existing stream","preventionTips":["Omit message_id to let the server generate unique ids","Check stream_exists before reusing an id for idempotent retries","Never hardcode message ids in tests"],"tags":["chat","async","streaming","duplicate","validation"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}