phalcon/cphalcon · warning · Phalcon\DataMapper\Pdo\Exception\OperationCancelled

Operation cancelled by a listener of '{eventName}'

Error message

Operation cancelled by a listener of '{eventName}'

What it means

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.

Source

Thrown at phalcon/DataMapper/Pdo/Connection/AbstractConnection.zep:913

        let this->profiler = profiler;

        return this;
    }

    /**
     * Fires a cancellable "before" event. A listener cancels by stopping the
     * event and returning false; see Phalcon\DataMapper\Pdo\Events for the
     * required idiom. The operation does not run when it is cancelled.
     *
     * @param string     $eventName
     * @param mixed|null $data
     *
     * @throws OperationCancelled
     */
    protected function fireBefore(string eventName, var data = null) -> void
    {
        if this->fireManagerEvent(eventName, data, true) === false {
            throw new OperationCancelled(eventName);
        }
    }

    /**
     * Bind a value using the proper PDO::PARAM_* type.
     *
     * @param \PDOStatement $statement
     * @param mixed         $name
     * @param mixed         $arguments
     */
    protected function performBind(
        <\PDOStatement> statement,
        var name,
        var arguments
    ) -> void {
        var key, parameters, type;

        let key = name;

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Fix the listener: return true (or nothing) when the operation should proceed; return false only to cancel deliberately
  2. Follow the exact listener idiom documented in Phalcon\DataMapper\Pdo\Events — stopping propagation alone is not what cancels, the false return is
  3. Catch OperationCancelled where aborted operations are expected (e.g., read-only mode) and handle it explicitly
  4. Do not blanket-catch generic Exception around queries — that would hide intentional cancellations and real PDO errors alike

Example fix

// before
$eventsManager->attach('beforeQuery', function ($event, $connection) {
    return strpos($connection->getSqlStatement(), 'FORBIDDEN'); // bool -> cancels when false
});

// after
$eventsManager->attach('beforeQuery', function ($event, $connection) {
    if (strpos($connection->getSqlStatement(), 'FORBIDDEN') !== false) {
        $event->stop();
        return false; // explicit, deliberate cancel
    }
    return true;
});
Defensive patterns

Strategy: try-catch

Try / catch

use Phalcon\DataMapper\Pdo\Exception\OperationCancelled;

try {
    $connection->query($sql);
} catch (OperationCancelled $e) {
    // a before-event listener deliberately vetoed the operation
    $logger->warning('Query cancelled by listener: ' . $sql);
}

Prevention

When it happens

Trigger: 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.

Common situations: Read-only replica guards blocking writes; auditing listeners that veto forbidden statements; a debugging listener that unintentionally returns false and cancels every query.

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/ca511be64b583a51. Report an issue: GitHub.