{"record":{"id":"ca511be64b583a51","repo":"phalcon/cphalcon","slug":"operation-cancelled-by-a-listener-of-eventname","errorCode":null,"errorMessage":"Operation cancelled by a listener of '{eventName}'","messagePattern":"Operation cancelled by a listener of '(.+?)'","errorType":"exception","errorClass":"Phalcon\\DataMapper\\Pdo\\Exception\\OperationCancelled","httpStatus":null,"severity":"warning","filePath":"phalcon/DataMapper/Pdo/Connection/AbstractConnection.zep","lineNumber":913,"sourceCode":"        let this->profiler = profiler;\n\n        return this;\n    }\n\n    /**\n     * Fires a cancellable \"before\" event. A listener cancels by stopping the\n     * event and returning false; see Phalcon\\DataMapper\\Pdo\\Events for the\n     * required idiom. The operation does not run when it is cancelled.\n     *\n     * @param string     $eventName\n     * @param mixed|null $data\n     *\n     * @throws OperationCancelled\n     */\n    protected function fireBefore(string eventName, var data = null) -> void\n    {\n        if this->fireManagerEvent(eventName, data, true) === false {\n            throw new OperationCancelled(eventName);\n        }\n    }\n\n    /**\n     * Bind a value using the proper PDO::PARAM_* type.\n     *\n     * @param \\PDOStatement $statement\n     * @param mixed         $name\n     * @param mixed         $arguments\n     */\n    protected function performBind(\n        <\\PDOStatement> statement,\n        var name,\n        var arguments\n    ) -> void {\n        var key, parameters, type;\n\n        let key = name;","sourceCodeStart":895,"sourceCodeEnd":931,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/DataMapper/Pdo/Connection/AbstractConnection.zep#L895-L931","documentation":"Before each major operation the connection fires a cancellable 'before' event (beforeQuery, beforeBeginTransaction, ...). If a listener stops the event and the manager returns false, fireBefore() throws OperationCancelled so the operation does not run. It is a control-flow exception: the database work was deliberately aborted, not failed.","triggerScenarios":"An EventsManager listener on beforeQuery/beforeBeginTransaction calls $event->stop() and returns false (query blacklist, read-only enforcement); a listener whose last expression is a falsy check result implicitly returned as false; listener code copied from Phalcon\\Di-era samples with different return conventions.","commonSituations":"Read-only replica guards blocking writes; auditing listeners that veto forbidden statements; a debugging listener that unintentionally returns false and cancels every query.","solutions":["Fix the listener: return true (or nothing) when the operation should proceed; return false only to cancel deliberately","Follow the exact listener idiom documented in Phalcon\\DataMapper\\Pdo\\Events — stopping propagation alone is not what cancels, the false return is","Catch OperationCancelled where aborted operations are expected (e.g., read-only mode) and handle it explicitly","Do not blanket-catch generic Exception around queries — that would hide intentional cancellations and real PDO errors alike"],"exampleFix":"// before\n$eventsManager->attach('beforeQuery', function ($event, $connection) {\n    return strpos($connection->getSqlStatement(), 'FORBIDDEN'); // bool -> cancels when false\n});\n\n// after\n$eventsManager->attach('beforeQuery', function ($event, $connection) {\n    if (strpos($connection->getSqlStatement(), 'FORBIDDEN') !== false) {\n        $event->stop();\n        return false; // explicit, deliberate cancel\n    }\n    return true;\n});","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"use Phalcon\\DataMapper\\Pdo\\Exception\\OperationCancelled;\n\ntry {\n    $connection->query($sql);\n} catch (OperationCancelled $e) {\n    // a before-event listener deliberately vetoed the operation\n    $logger->warning('Query cancelled by listener: ' . $sql);\n}","preventionTips":["Write before-event listeners to return true explicitly on the success path","Only return false (with $event->stop()) when cancellation is the intended outcome","Register a dedicated catch for OperationCancelled wherever policy listeners can veto operations"],"tags":["pdo","events","event-manager","cancellation","phalcon"],"backgroundTag":"event-propagation-stopped","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}