{"id":"c24ecb7682619974","repo":"laravel/framework","slug":"transactions-manager-has-not-been-set","errorCode":null,"errorMessage":"Transactions Manager has not been set.","messagePattern":"Transactions Manager has not been set\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/Illuminate/Database/Concerns/ManagesTransactions.php","lineNumber":360,"sourceCode":"    {\n        return $this->transactions;\n    }\n\n    /**\n     * Execute the callback after a transaction commits.\n     *\n     * @param  callable  $callback\n     * @return void\n     *\n     * @throws \\RuntimeException\n     */\n    public function afterCommit($callback)\n    {\n        if ($this->transactionsManager) {\n            return $this->transactionsManager->addCallback($callback);\n        }\n\n        throw new RuntimeException('Transactions Manager has not been set.');\n    }\n\n    /**\n     * Execute the callback after a transaction rolls back.\n     *\n     * @param  callable  $callback\n     * @return void\n     *\n     * @throws \\RuntimeException\n     */\n    public function afterRollBack($callback)\n    {\n        if ($this->transactionsManager) {\n            return $this->transactionsManager->addCallbackForRollback($callback);\n        }\n\n        throw new RuntimeException('Transactions Manager has not been set.');\n    }","sourceCodeStart":342,"sourceCodeEnd":378,"githubUrl":"https://github.com/laravel/framework/blob/bd6b5437e6ad87bb49f9b426724f07a9f64e9683/src/Illuminate/Database/Concerns/ManagesTransactions.php#L342-L378","documentation":"Thrown by Connection::afterCommit (and afterRollBack) when $this->transactionsManager is null. Laravel's transaction lifecycle relies on a TransactionsManager instance to register callbacks that must fire after commit; if it was never set on the connection, afterCommit cannot schedule the callback and throws RuntimeException.","triggerScenarios":"Calling DB::afterCommit(fn () => ...) on a connection where the transactions manager was not wired (e.g. a manually-constructed Connection, a custom connection extending Connection, or test setups using DB::connection without bootstrapping the manager).","commonSituations":"Unit tests constructing a bare Connection or using an in-memory driver that skips the manager; custom database connection classes that override setTransactionManager or never receive one; package that creates connections directly bypassing the DatabaseManager; calling afterCommit outside a transactional context after the manager was reset.","solutions":["Obtain the connection through the DatabaseManager (DB::connection()) so the transactions manager is set automatically.","Inject/call $connection->setTransactionManager($manager) if you construct connections manually.","Guard the call: if (DB::transactionLevel() > 0) DB::afterCommit($cb); else $cb(); to fire immediately when not in a transaction.","In tests, use Illuminate\\Foundation\\Testing\\RefreshDatabase or the in-memory SQLite via the framework so the manager is bootstrapped."],"exampleFix":"// before\n$conn = new Illuminate\\Database\\MySqlConnection($pdo, '', '');\n$conn->afterCommit(fn () => event(new OrderShipped));\n// throws 'Transactions Manager has not been set.'\n\n// after\n$conn = DB::connection(); // manager wired by framework\n$conn->afterCommit(fn () => event(new OrderShipped));","handlingStrategy":"validation","validationCode":"$conn = DB::connection();\nif (! $conn->getTransactionManager()) {\n    // manager missing; fire callback immediately or wire the manager\n    $cb();\n    return;\n}\n$conn->afterCommit($cb);","typeGuard":"function connectionHasTransactionManager(\\Illuminate\\Database\\Connection $c): bool\n{\n    return method_exists($c, 'getTransactionManager') && $c->getTransactionManager() !== null;\n}","tryCatchPattern":"try {\n    DB::afterCommit($cb);\n} catch (\\RuntimeException $e) {\n    if (str_contains($e->getMessage(), 'Transactions Manager has not been set')) {\n        $cb(); // fire immediately when outside framework\n    } else throw $e;\n}","preventionTips":["Always obtain connections via DB::connection() to ensure the manager is wired.","Guard afterCommit calls with a transactionLevel() check.","In tests, use RefreshDatabase so the framework bootstraps the manager."],"tags":["database","transactions","after-commit","configuration"],"analyzedSha":"bd6b5437e6ad87bb49f9b426724f07a9f64e9683","analyzedAt":"2026-08-06T00:28:32.783Z","schemaVersion":2}