{"record":{"id":"e67b963244413fcb","repo":"microsoft/semantic-kernel","slug":"user-stopped-the-operation","errorCode":null,"errorMessage":"User stopped the operation","messagePattern":"User stopped the operation","errorType":"exception","errorClass":"OperationCancelledException","httpStatus":null,"severity":"info","filePath":"python/samples/concepts/filtering/function_invocation_filters.py","lineNumber":36,"sourceCode":"\n\n# A filter is a piece of custom code that runs at certain points in the process\n# this sample has a filter that is called during Function Invocation for non-streaming function.\n# You can name the function itself with arbitrary names, but the signature needs to be:\n# `context, next`\n# You are then free to run code before the call to the next filter or the function itself.\n# and code afterwards.\nasync def input_output_filter(\n    context: FunctionInvocationContext,\n    next: Callable[[FunctionInvocationContext], Coroutine[Any, Any, None]],\n) -> None:\n    if context.function.plugin_name != \"chat\":\n        await next(context)\n        return\n    try:\n        user_input = input(\"User:> \")\n    except (KeyboardInterrupt, EOFError) as exc:\n        raise OperationCancelledException(\"User stopped the operation\") from exc\n    if user_input == \"exit\":\n        raise OperationCancelledException(\"User stopped the operation\")\n    context.arguments[\"chat_history\"].add_user_message(user_input)\n\n    await next(context)\n\n    if context.result:\n        logger.info(f\"Usage: {context.result.metadata.get('usage')}\")\n        context.arguments[\"chat_history\"].add_message(context.result.value[0])\n        print(f\"Mosscap:> {context.result!s}\")\n\n\nasync def main() -> None:\n    kernel = Kernel()\n    kernel.add_service(AzureChatCompletion(service_id=\"chat-gpt\", credential=AzureCliCredential()))\n    kernel.add_plugin(\n        parent_directory=os.path.join(os.path.dirname(os.path.realpath(__file__)), \"resources\"), plugin_name=\"chat\"\n    )","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/samples/concepts/filtering/function_invocation_filters.py#L18-L54","documentation":"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.","triggerScenarios":"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').","commonSituations":"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.","solutions":["Treat this as a normal exit: catch OperationCancelledException at the top level and exit cleanly.","If running non-interactively, replace input() with a different source (a queue, a file) or drive the chat without this filter.","Press 'exit' (the string) to stop gracefully without relying on Ctrl-C/Ctrl-D."],"exampleFix":"# before - cancellation propagates uncaught\ntry:\n    user_input = input(\"User:> \")\nexcept (KeyboardInterrupt, EOFError) as exc:\n    raise OperationCancelledException(\"User stopped the operation\") from exc\n# after - handle at the call site\nfrom semantic_kernel.exceptions import OperationCancelledException\ntry:\n    await kernel.invoke(chat_function)\nexcept OperationCancelledException:\n    print(\"\\nGoodbye!\")\n    return","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"def is_cancellation(exc: BaseException) -> bool:\n    from semantic_kernel.exceptions import OperationCancelledException\n    return isinstance(exc, OperationCancelledException)","tryCatchPattern":"from semantic_kernel.exceptions import OperationCancelledException\n\ntry:\n    await kernel.invoke(chat_function)\nexcept OperationCancelledException:\n    print(\"\\nChat cancelled by user.\")\n    return","preventionTips":["Always catch OperationCancelledException at the top level of an interactive sample.","Provide a non-exception exit (e.g. typing 'exit') to avoid relying on signals.","Run interactive samples in a real TTY so EOF behaves predictably."],"tags":["python","sample","filters","cancellation","interactive"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}