microsoft/semantic-kernel · error · AgentThreadOperationException
The thread could not be deleted due to an error response fro
Error message
The thread could not be deleted due to an error response from the service.
What it means
Raised as AgentThreadOperationException by AssistantAgentThread._delete when the underlying client.beta.threads.delete() call throws. The original service exception is chained (from ex), preserving the real cause (auth, not-found, network, rate limit).
Source
Thrown at python/semantic_kernel/agents/open_ai/openai_assistant_agent.py:190
messages=self._messages,
metadata=self._metadata,
tool_resources=self._tool_resources,
)
except Exception as ex:
raise AgentThreadOperationException(
"The thread could not be created due to an error response from the service."
) from ex
return response.id
@override
async def _delete(self) -> None:
"""Ends the current thread."""
if self._id is None:
raise AgentThreadOperationException("The thread cannot be deleted because it has not been created yet.")
try:
await self._client.beta.threads.delete(self._id)
except Exception as ex:
raise AgentThreadOperationException(
"The thread could not be deleted due to an error response from the service."
) from ex
@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)
# Only add the message to the thread if it's not already there
if (
not new_message.metadata
or "thread_id" not in new_message.metadata
or new_message.metadata["thread_id"] != self._id
):
assert self._id is not None # nosec
await AssistantThreadActions.create_message(self._client, self._id, new_message)
View on GitHub (pinned to c028a0c7dc)
Solutions
- Inspect the chained __cause__ for the actual status (404 = already gone, 401/403 = auth, 429 = rate limit).
- Treat 404 as benign in cleanup (the thread is already deleted).
- Retry with backoff for 429/5xx; refresh credentials for 401/403.
- Avoid double-deleting; track deletion state.
Example fix
# before
try:
await thread.delete()
except AgentThreadOperationException:
pass # swallows real cause
# after
try:
await thread.delete()
except AgentThreadOperationException as e:
cause = e.__cause__
if getattr(cause, "status_code", None) == 404:
logging.info("thread already deleted")
else:
raise Defensive patterns
Strategy: try-catch
Try / catch
import asyncio
from semantic_kernel.exceptions.agent_exceptions import AgentThreadOperationException
async def safe_delete(thread, attempts=3):
for i in range(attempts):
try:
return await thread.delete()
except AgentThreadOperationException as e:
cause = e.__cause__
status = getattr(cause, "status_code", None)
if status == 404:
logging.info("thread already deleted")
return
if status in (429, 500, 502, 503) and i < attempts - 1:
await asyncio.sleep(2 ** i)
continue
raise Prevention
- Treat a 404 cause as benign during cleanup (already deleted).
- Retry transient 429/5xx with backoff.
- Track deletion state to avoid double-delete attempts.
When it happens
Trigger: Calling thread.delete() (valid id present) when the OpenAI service rejects the delete: the thread id no longer exists, credentials are invalid/expired, rate limited, or a network error occurs.
Common situations: Deleting a thread that was already deleted; expired token; race condition where the thread was removed elsewhere; transient network failures.
Related errors
- The thread could not be created due to an error response fro
- The message could not be added to the thread due to an error
- Client cannot be None
- The thread cannot be deleted because it has not been created
- The thread could not be created due to an error response fro
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/52dadb4eb1e5c2a6.
Report an issue: GitHub.