microsoft/semantic-kernel · info · OperationCancelledException

User stopped the operation

Error message

User stopped the operation

What it means

OperationCancelledException raised by the function-invocation filter sample when input() is interrupted: KeyboardInterrupt (Ctrl-C) or EOFError (Ctrl-D / closed stdin) is caught and re-raised as a Semantic Kernel OperationCancelledException, signalling the user is ending the interactive chat. It surfaces a deliberate, benign cancellation, not a fault.

Source

Thrown at python/samples/concepts/filtering/function_invocation_filters.py:36


# A filter is a piece of custom code that runs at certain points in the process
# this sample has a filter that is called during Function Invocation for non-streaming function.
# You can name the function itself with arbitrary names, but the signature needs to be:
# `context, next`
# You are then free to run code before the call to the next filter or the function itself.
# and code afterwards.
async def input_output_filter(
    context: FunctionInvocationContext,
    next: Callable[[FunctionInvocationContext], Coroutine[Any, Any, None]],
) -> None:
    if context.function.plugin_name != "chat":
        await next(context)
        return
    try:
        user_input = input("User:> ")
    except (KeyboardInterrupt, EOFError) as exc:
        raise OperationCancelledException("User stopped the operation") from exc
    if user_input == "exit":
        raise OperationCancelledException("User stopped the operation")
    context.arguments["chat_history"].add_user_message(user_input)

    await next(context)

    if context.result:
        logger.info(f"Usage: {context.result.metadata.get('usage')}")
        context.arguments["chat_history"].add_message(context.result.value[0])
        print(f"Mosscap:> {context.result!s}")


async def main() -> None:
    kernel = Kernel()
    kernel.add_service(AzureChatCompletion(service_id="chat-gpt", credential=AzureCliCredential()))
    kernel.add_plugin(
        parent_directory=os.path.join(os.path.dirname(os.path.realpath(__file__)), "resources"), plugin_name="chat"
    )

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Treat this as a normal exit: catch OperationCancelledException at the top level and exit cleanly.
  2. If running non-interactively, replace input() with a different source (a queue, a file) or drive the chat without this filter.
  3. Press 'exit' (the string) to stop gracefully without relying on Ctrl-C/Ctrl-D.

Example fix

# before - cancellation propagates uncaught
try:
    user_input = input("User:> ")
except (KeyboardInterrupt, EOFError) as exc:
    raise OperationCancelledException("User stopped the operation") from exc
# after - handle at the call site
from semantic_kernel.exceptions import OperationCancelledException
try:
    await kernel.invoke(chat_function)
except OperationCancelledException:
    print("\nGoodbye!")
    return
Defensive patterns

Strategy: try-catch

Type guard

def is_cancellation(exc: BaseException) -> bool:
    from semantic_kernel.exceptions import OperationCancelledException
    return isinstance(exc, OperationCancelledException)

Try / catch

from semantic_kernel.exceptions import OperationCancelledException

try:
    await kernel.invoke(chat_function)
except OperationCancelledException:
    print("\nChat cancelled by user.")
    return

Prevention

When it happens

Trigger: During the chat loop, the filter calls input('User:> '). The user presses Ctrl-C (KeyboardInterrupt) or Ctrl-D (EOFError, end of stdin). The except catches both and raises OperationCancelledException('User stopped the operation').

Common situations: Running the interactive sample in a terminal and pressing Ctrl-C/Ctrl-D to quit; running the sample under a non-interactive runner where stdin is closed; or piping input that ends.

Related errors


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