microsoft/semantic-kernel · error · AgentThreadOperationException
Cannot retrieve chat history, since the thread has been dele
Error message
Cannot retrieve chat history, since the thread has been deleted.
What it means
Thrown by AutoGenConversableAgentThread.get_messages when the thread's _is_deleted flag is True. Once delete() has run, the in-memory chat history is cleared and the thread is marked deleted, so any subsequent attempt to read messages is rejected as an invalid operation on a dead thread.
Source
Thrown at python/semantic_kernel/agents/autogen/autogen_conversable_agent.py:89
"""Called when a new message has been contributed to the chat."""
if isinstance(new_message, str):
new_message = ChatMessageContent(role=AuthorRole.USER, content=new_message)
if (
not new_message.metadata
or "thread_id" not in new_message.metadata
or new_message.metadata["thread_id"] != self._id
):
self._chat_history.add_message(new_message)
async def get_messages(self) -> AsyncIterable[ChatMessageContent]:
"""Retrieve the current chat history.
Returns:
An async iterable of ChatMessageContent.
"""
if self._is_deleted:
raise AgentThreadOperationException("Cannot retrieve chat history, since the thread has been deleted.")
if self._id is None:
await self.create()
for message in self._chat_history.messages:
yield message
async def reduce(self) -> ChatHistory | None:
"""Reduce the chat history to a smaller size."""
if self._id is None:
raise AgentThreadOperationException("Cannot reduce chat history, since the thread is not currently active.")
if not isinstance(self._chat_history, ChatHistoryReducer):
return None
return await self._chat_history.reduce()
@experimental
class AutoGenConversableAgent(Agent):
"""A Semantic Kernel wrapper around an AutoGen 0.2 `ConversableAgent`.
View on GitHub (pinned to c028a0c7dc)
Solutions
- Do not call get_messages after delete(); reorder logic so reads happen before cleanup.
- Create a fresh thread (new AutoGenConversableAgentThread) if you need history after deletion.
- Track deletion state in your own code and short-circuit reads when deleted.
Example fix
# before await thread.delete() msgs = [m async for m in thread.get_messages()] # after msgs = [m async for m in thread.get_messages()] await thread.delete()
Defensive patterns
Strategy: validation
Validate before calling
if thread._is_deleted:
raise RuntimeError('thread already deleted; cannot read messages') Type guard
def thread_is_readable(thread) -> bool:
return not getattr(thread, '_is_deleted', False) Try / catch
from semantic_kernel.exceptions.agent_exceptions import AgentThreadOperationException
try:
messages = [m async for m in thread.get_messages()]
except AgentThreadOperationException as e:
if 'has been deleted' in str(e):
messages = []
else:
raise Prevention
- Read thread state before deleting.
- Do not share a thread reference across code that may delete it.
When it happens
Trigger: Calling `async for m in thread.get_messages()` after `await thread.delete()`; reusing a thread reference that another code path already deleted.
Common situations: Cleanup-then-inspect flow in tests or shutdown hooks; shared thread object deleted by a finally block before a later read; chaining agents where one deletes the thread.
Related errors
- Cannot reduce chat history, since the thread is not currentl
- Thread has been deleted; call `create()` to recreate it.
- Cannot create thread because it has already been deleted.
- This thread has been deleted and cannot be used anymore.
- This thread has been deleted and cannot be recreated.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/2502226b0b7ae1b2.
Report an issue: GitHub.