microsoft/semantic-kernel · warning · RuntimeError
The invocation has already been canceled.
Error message
The invocation has already been canceled.
What it means
OrchestrationResult.cancel() first checks whether the cancellation token is already canceled and refuses a double-cancel. Cancellation is idempotent by design; calling cancel() twice is a usage error.
Source
Thrown at python/semantic_kernel/agents/orchestration/orchestration_base.py:76
else:
await self.event.wait()
if self.value is None:
if self.cancellation_token.is_cancelled():
raise RuntimeError("The invocation was canceled before it could complete.")
if self.exception is not None:
raise self.exception
raise RuntimeError("The invocation did not produce a result.")
return self.value
def cancel(self) -> None:
"""Cancel the invocation.
This method will cancel the invocation.
Actors that have received messages will continue to process them, but no new messages will be processed.
"""
if self.cancellation_token.is_cancelled():
raise RuntimeError("The invocation has already been canceled.")
if self.event.is_set():
raise RuntimeError("The invocation has already been completed.")
self.cancellation_token.cancel()
self.event.set()
@experimental
class OrchestrationBase(ABC, Generic[TIn, TOut]):
"""Base class for multi-agent orchestration."""
t_in: type[TIn] | None = None
t_out: type[TOut] | None = None
def __init__(
self,
members: list[Agent],
name: str | None = None,View on GitHub (pinned to c028a0c7dc)
Solutions
- Guard cancel() with `if not result.cancellation_token.is_cancelled(): result.cancel()`.
- Centralize cancellation in one place (e.g. a single finally block) rather than canceling from multiple handlers.
- Track cancellation state yourself and skip redundant calls.
Example fix
// before
result.cancel()
result.cancel() # raises 'already been canceled'
// after
result.cancel()
if not result.cancellation_token.is_cancelled():
result.cancel() Defensive patterns
Strategy: validation
Validate before calling
# Idempotent cancel
if not result.cancellation_token.is_cancelled():
result.cancel() Type guard
def result_already_canceled(result) -> bool:
return result.cancellation_token.is_cancelled() Prevention
- Cancel from a single place (e.g. one finally block).
- Guard cancel() with the is_cancelled() check.
- Avoid wiring multiple handlers to cancel the same result.
When it happens
Trigger: Calling `result.cancel()` more than once on the same OrchestrationResult instance.
Common situations: A cleanup/finally block that cancels, combined with another cancel on timeout or error. Multiple components (e.g. a timeout handler and a shutdown handler) both canceling the same result.
Related errors
- The invocation was canceled before it could complete.
- The invocation has already been completed.
- The invocation did not produce a result.
- A complete listen_for condition is required for orchestratio
- At least one then action is required for orchestration steps
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/8ea0c91fa67e49f9.
Report an issue: GitHub.