microsoft/semantic-kernel · error · AgentThreadOperationException

Cannot delete the thread, since it has not been created.

Error message

Cannot delete the thread, since it has not been created.

What it means

Raised by CopilotStudioAgentThread._delete() when conversation_id is None and the thread has not already been deleted. Since _delete() is idempotent for already-deleted threads (early return), this error only fires on the first delete attempt of a thread that never had a conversation started. It is an AgentThreadOperationException.

Source

Thrown at python/semantic_kernel/agents/copilot_studio/copilot_studio_agent.py:246

    @override
    @property
    def id(self) -> str | None:
        """Get the thread ID."""
        return self.conversation_id

    @override
    async def _create(self) -> str:
        # Creation is deferred to CopilotStudioAgent._ensure_conversation.
        if self._is_deleted:
            raise AgentThreadOperationException("Cannot create a thread that has been deleted.")
        return ""

    @override
    async def _delete(self) -> None:
        if self._is_deleted:
            return
        if self.conversation_id is None:
            raise AgentThreadOperationException("Cannot delete the thread, since it has not been created.")
        self._conversation_id = None
        self._is_deleted = True

    @override
    async def _on_new_message(self, new_message: ChatMessageContent) -> None:
        raise NotImplementedError(
            "This method is not implemented for CopilotStudioAgent. "
            "Messages and responses are automatically handled by the Copilot Agent."
        )


@experimental
class CopilotStudioAgent(Agent):
    """Semantic Kernel abstraction over a Copilot Studio Agent."""

    client: CopilotClient
    channel_type: ClassVar[type[AgentChannel] | None] = None

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Guard the delete call: only delete if thread.conversation_id is not None.
  2. Move thread creation closer to first use so it is always populated before cleanup.
  3. Let the agent manage the thread lifecycle by not passing an explicit thread, so there is nothing to manually delete.

Example fix

# before
thread = CopilotStudioAgentThread(agent.client)
await thread.delete()  # raises — never started

# after
thread = CopilotStudioAgentThread(agent.client)
if thread.conversation_id is not None:
    await thread.delete()
Defensive patterns

Strategy: validation

Validate before calling

if thread.conversation_id is not None:
    await thread.delete()

Try / catch

from semantic_kernel.exceptions.agent_exceptions import AgentThreadOperationException

try:
    await thread.delete()
except AgentThreadOperationException:
    pass  # nothing to delete; safe to ignore

Prevention

When it happens

Trigger: Constructing a CopilotStudioAgentThread and calling thread.delete() before any agent invocation that would populate conversation_id via _ensure_conversation.

Common situations: Cleanup/teardown in a finally block that runs even when the conversation was never started; early-exit error paths that attempt to delete a thread that was created but never used.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/12a095187af4ee8e. Report an issue: GitHub.