microsoft/semantic-kernel · warning · OperationCanceledException

Delivery of message {messageId} was cancelled.

Error message

Delivery of message {messageId} was cancelled.

What it means

InProcessRuntime.SendMessageAsync awaits the delivery's ResultSink.Future; if it faults with TargetInvocationException wrapping OperationCanceledException, the catch unwraps and rethrows a new OperationCanceledException naming the messageId. This is the normal propagation when a message delivery is cancelled (explicit token, agent-side cancellation, or runtime shutdown).

Source

Thrown at dotnet/src/Agents/Runtime/InProcess/InProcessRuntime.cs:142

    public async ValueTask<object?> SendMessageAsync(object message, AgentId recipient, AgentId? sender = null, string? messageId = null, CancellationToken cancellationToken = default)
    {
        return await this.ExecuteTracedAsync(async () =>
        {
            MessageDelivery delivery =
                new MessageEnvelope(message, messageId, cancellationToken)
                    .WithSender(sender)
                    .ForSend(recipient, this.SendMessageServicerAsync);

            this._messageDeliveryQueue.Enqueue(delivery);
            Interlocked.Increment(ref this.messageQueueCount);

            try
            {
                return await delivery.ResultSink.Future.ConfigureAwait(false);
            }
            catch (TargetInvocationException ex) when (ex.InnerException is OperationCanceledException innerOCEx)
            {
                throw new OperationCanceledException($"Delivery of message {messageId} was cancelled.", innerOCEx);
            }
        }).ConfigureAwait(false);
    }

    /// <inheritdoc/>
    public async ValueTask<AgentId> GetAgentAsync(AgentId agentId, bool lazy = true)
    {
        if (!lazy)
        {
            await this.EnsureAgentAsync(agentId).ConfigureAwait(false);
        }

        return agentId;
    }

    /// <inheritdoc/>
    public ValueTask<AgentId> GetAgentAsync(AgentType agentType, string key = AgentId.DefaultKey, bool lazy = true)
        => this.GetAgentAsync(new AgentId(agentType, key), lazy);

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. If cancellation is expected, catch OperationCanceledException and treat it as non-fatal.
  2. Ensure your CancellationToken is not cancelled prematurely (check timeout/CancellationTokenSource configuration).
  3. Avoid calling StopAsync while RPC sends are still awaited if you need their results.

Example fix

// before
object? reply = await runtime.SendMessageAsync(msg, recipient, cancellationToken: cts.Token);

// after
try
{
    object? reply = await runtime.SendMessageAsync(msg, recipient, cancellationToken: cts.Token);
}
catch (OperationCanceledException) when (cts.IsCancellationRequested)
{
    // expected cancellation; handle gracefully
}
Defensive patterns

Strategy: try-catch

Try / catch

try { object? reply = await runtime.SendMessageAsync(msg, recipient, cancellationToken: ct); }
catch (OperationCanceledException) when (ct.IsCancellationRequested)
{
    // expected cancellation; do not treat as fatal
}

Prevention

When it happens

Trigger: The caller's CancellationToken passed to SendMessageAsync is cancelled mid-delivery; the runtime's shutdown token (_shutdownSource) cancels pending deliveries; the receiving agent throws OperationCanceledException; StopAsync fires while an RPC send is in flight.

Common situations: Request timeouts implemented via CancellationTokenSource.CancelAfter; user-initiated cancel; graceful shutdown that aborts in-flight sends; an agent whose handler honors cancellation.

Related errors


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