microsoft/semantic-kernel · error · InvalidOperationException
This thread cannot be deleted, since it has not been created
Error message
This thread cannot be deleted, since it has not been created.
What it means
Thrown by AgentThread.DeleteAsync when the thread was never created on the backend (this.Id is null). The base AgentThread lifecycle requires that CreateAsync (or a resume-from-existing-id constructor) has run first, setting the Id property, before deletion is meaningful. The method short-circuits with a no-op if already deleted, but rejects deletion of a never-started thread.
Source
Thrown at dotnet/src/Agents/Abstractions/AgentThread.cs:116
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
}
/// <summary>
/// Deletes the current thread.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
/// <returns>A task that completes when the thread has been deleted.</returns>
/// <exception cref="InvalidOperationException">The thread was never created.</exception>
public virtual async Task DeleteAsync(CancellationToken cancellationToken = default)
{
if (this.IsDeleted)
{
return;
}
if (this.Id is null)
{
throw new InvalidOperationException("This thread cannot be deleted, since it has not been created.");
}
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
await this.AIContextProviders.ConversationDeletingAsync(this.Id, cancellationToken).ConfigureAwait(false);
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
await this.DeleteInternalAsync(cancellationToken).ConfigureAwait(false);
this.IsDeleted = true;
}
/// <summary>
/// This method is called when a new message has been contributed to the chat by any participant.
/// </summary>
/// <remarks>
/// Inheritors can use this method to update their context based on the new message.
/// </remarks>
/// <param name="newMessage">The new message.</param>View on GitHub (pinned to c028a0c7dc)
Solutions
- Check thread.Id is not null before calling DeleteAsync, or call CreateAsync first.
- Guard with: if (!thread.IsDeleted && thread.Id is not null) await thread.DeleteAsync(ct);
- Restructure cleanup logic so DeleteAsync only runs in a finally block when creation has already succeeded.
Example fix
// before
var thread = new AzureAIAgentThread(client);
await thread.DeleteAsync(ct); // throws
// after
var thread = new AzureAIAgentThread(client);
if (thread.Id is not null && !thread.IsDeleted)
{
await thread.DeleteAsync(ct);
} Defensive patterns
Strategy: validation
Validate before calling
if (thread is { IsDeleted: false, Id: null })
{
// Thread was never created; skip or create first
return; // or await thread.CreateAsync(ct);
} Try / catch
try
{
await thread.DeleteAsync(ct);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("has not been created"))
{
// Thread was never created; nothing to clean up
_logger.LogDebug("Thread was never created, skipping deletion.");
} Prevention
- Track thread creation state in a wrapper or local variable.
- Only call DeleteAsync in a finally block that runs after successful creation.
- Use the two-argument constructor AzureAIAgentThread(client, existingId) when resuming to set Id immediately.
When it happens
Trigger: Calling thread.DeleteAsync() on a fresh AgentThread instance whose CreateAsync was never invoked and that was not constructed with an existing thread Id. This can also happen if the first message that would trigger lazy creation (via OnNewMessageAsync) was never sent.
Common situations: Developer creates an AzureAIAgentThread(client) (no id overload), then immediately calls DeleteAsync without ever invoking the agent or calling CreateAsync. Also occurs in cleanup/disposal paths that run even when the main workflow threw before thread creation.
Related errors
- This thread has been deleted and cannot be used anymore.
- AIContextProviders with AIFunctions are not supported when A
- AzureAI agents client not found.
- The agent thread is not a ChatHistoryAgentThread.
- 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/d53b6b9f606f9af0.
Report an issue: GitHub.