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
Raised by ResponsesAgentThread.get_messages() when self._is_deleted is True. The thread object remembers a deleted flag set by its delete() method, and any subsequent attempt to read back the chat history is refused. This is a guard against using stale thread state after the backing OpenAI Responses resource (or local history) has been discarded.
Source
Thrown at python/semantic_kernel/agents/open_ai/openai_responses_agent.py:230
raise AgentThreadOperationException("Cannot delete the thread, since it has not been created.")
self._chat_history.clear()
self._is_deleted = True
@override
async def _on_new_message(self, new_message: str | ChatMessageContent) -> None:
"""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 self.response_id:
self._chat_history.add_message(new_message)
async def get_messages(
self, limit: int | None = None, sort_order: Literal["asc", "desc"] | None = "desc"
) -> AsyncIterable[ChatMessageContent]:
"""Retrieve the current chat history."""
if self._is_deleted:
raise AgentThreadOperationException("Cannot retrieve chat history, since the thread has been deleted.")
if self.store_enabled and self.response_id is not None:
async for message in ResponsesAgentThreadActions.get_messages(
self._client,
self.response_id,
limit=limit,
sort_order=sort_order,
):
yield message
else:
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 NoneView on GitHub (pinned to c028a0c7dc)
Solutions
- Stop calling get_messages() on a thread you already deleted; capture the messages you need before calling delete().
- After delete(), set the variable to None / create a new ResponsesAgentThread so downstream code cannot reach the stale instance.
- If you need history after deletion, read it into a local list first, then delete, then operate on the local copy.
Example fix
// before await thread.delete() history = await thread.get_messages() # raises // after history = [m async for m in thread.get_messages()] await thread.delete()
Defensive patterns
Strategy: validation
Validate before calling
# Before reading history, confirm the thread is not deleted
if not getattr(thread, '_is_deleted', False):
messages = [m async for m in thread.get_messages()]
else:
messages = [] Type guard
def is_thread_usable(thread) -> bool:
return not getattr(thread, '_is_deleted', False) and thread is not None Try / catch
from semantic_kernel.exceptions.agent_exceptions import AgentThreadOperationException
try:
async for msg in thread.get_messages():
...
except AgentThreadOperationException:
# thread already deleted; use previously captured history
pass Prevention
- Capture messages into a local list before calling thread.delete().
- Set thread variables to None after deletion to prevent reuse.
- Treat delete() as terminal — never read from a deleted thread.
When it happens
Trigger: Calling await thread.get_messages(...) on a ResponsesAgentThread after thread.delete() has already been awaited on that same instance. The _is_deleted flag is set during delete() and never cleared, so every subsequent get_messages() / reduce iteration hits the guard.
Common situations: A cleanup routine deletes the thread and then a follow-up handler (logging, audit, or a retry path) tries to read messages. Also happens when a thread object is shared across coroutines and one path deletes it while another still reads. Rewinding or reusing a thread variable after explicit deletion is the typical cause.
Related errors
- Cannot reduce chat history, since the thread is not currentl
- This thread cannot be deleted, since it has not been created
- The agent thread is not a ChatHistoryAgentThread.
- The thread could not be created due to an error response fro
- The thread could not be deleted due to an error response fro
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/0c86528c6fa211a3.
Report an issue: GitHub.