{"record":{"id":"bb5c53f88ea66af2","repo":"microsoft/semantic-kernel","slug":"the-thread-has-been-deleted-bb5c53","errorCode":null,"errorMessage":"The thread has been deleted.","messagePattern":"The thread has been deleted\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/agents/open_ai/openai_assistant_agent.py","lineNumber":219,"sourceCode":"        if (\n            not new_message.metadata\n            or \"thread_id\" not in new_message.metadata\n            or new_message.metadata[\"thread_id\"] != self._id\n        ):\n            assert self._id is not None  # nosec\n            await AssistantThreadActions.create_message(self._client, self._id, new_message)\n\n    async def get_messages(self, sort_order: Literal[\"asc\", \"desc\"] | None = None) -> AsyncIterable[ChatMessageContent]:\n        \"\"\"Get the messages in the thread.\n\n        Args:\n            sort_order: The order to sort the messages in. Either \"asc\" or \"desc\".\n\n        Yields:\n            An AsyncIterable of ChatMessageContent of the messages in the thread.\n        \"\"\"\n        if self._is_deleted:\n            raise ValueError(\"The thread has been deleted.\")\n        if self._id is None:\n            await self.create()\n        assert self.id is not None  # nosec\n        async for message in AssistantThreadActions.get_messages(self._client, self.id, sort_order=sort_order):\n            yield message\n\n\n@release_candidate\n@register_agent_type(\"openai_assistant\")\nclass OpenAIAssistantAgent(DeclarativeSpecMixin, Agent):\n    \"\"\"OpenAI Assistant Agent class.\n\n    Provides the ability to interact with OpenAI Assistants.\n    \"\"\"\n\n    # region Agent Initialization\n\n    client: AsyncOpenAI","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/agents/open_ai/openai_assistant_agent.py#L201-L237","documentation":"Raised as a plain ValueError by AssistantAgentThread.get_messages() after the thread's _delete() already ran. The thread object tracks an internal _is_deleted flag; once true, the OpenAI thread id is gone server-side so listing messages has no valid target. Calling get_messages on a deleted thread is a state-machine violation, not a network failure.","triggerScenarios":"You call await thread.delete() (or _delete()) and then later call await thread.get_messages(...) on the same AssistantAgentThread instance. Also occurs if delete() ran as part of chat teardown and a follow-up component still holds the old thread reference and queries messages.","commonSituations":"Reusing a thread variable across conversation turns in a long-lived agent; cleanup hooks that delete the thread while a parallel coroutine is still reading history; agent-chat finishers that delete then log messages.","solutions":["Do not call get_messages() after delete(); create a fresh AssistantAgentThread for a new conversation.","Guard the call with the thread's lifecycle state or recreate the thread before reading.","Ensure no concurrent coroutines delete the thread while another reads it."],"exampleFix":"// before\nawait thread.delete()\nmsgs = [m async for m in thread.get_messages()]\n\n// after\nmsgs = [m async for m in thread.get_messages()]\nawait thread.delete()","handlingStrategy":"validation","validationCode":"if getattr(thread, '_is_deleted', False):\n    raise RuntimeError('thread already deleted; create a new one')\nmessages = [m async for m in thread.get_messages()]","typeGuard":"def thread_is_alive(thread: AssistantAgentThread) -> bool:\n    return not getattr(thread, '_is_deleted', False)","tryCatchPattern":"try:\n    msgs = [m async for m in thread.get_messages()]\nexcept ValueError as e:\n    if 'deleted' in str(e):\n        thread = AssistantAgentThread(client=client)\n    else:\n        raise","preventionTips":["Never read messages after delete(); order teardown last.","Replace the thread reference on reset instead of mutating state.","Track thread lifecycle in your own state machine."],"tags":["thread-lifecycle","agents","openai-assistant","state"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}