{"record":{"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/e0f6eb3518ac29fbbca8529e97d0df7fc9f24481/src/Illuminate/Database/Concerns/ManagesTransactions.php#L342-L378","documentation":"RuntimeException from afterCommit() when the transactions manager ($transactionsManager) is not set on the connection. afterCommit() defers a callback until the surrounding transaction commits; without a manager to track transaction state there is nothing to defer onto, so the call is rejected rather than silently dropped.","triggerScenarios":"Calling DB::connection()->afterCommit(...) outside of any transaction context; calling afterCommit on a connection before a transaction manager is attached (e.g. in low-level/CLI bootstrapping or with a custom connection); using a connection type that does not initialize the transactions manager.","commonSituations":"Model observers/listeners calling afterCommit when invoked from a queue worker or CLI command with no active DB transaction; testing with a connection that bypasses normal Laravel bootstrapping; using afterCommit where you actually mean after the immediate save regardless of transactions.","solutions":["Guard the call: only register an afterCommit callback when inside a transaction, e.g. if (DB::connection()->transactionLevel() > 0) { ... } else { run it immediately }.","Wrap the work in DB::transaction() so a transactions manager is established before afterCommit is called.","If the callback should run regardless, skip afterCommit and run the logic directly (or dispatch a job).","Ensure the connection is fully bootstrapped via the standard Laravel DB facade/service-provider wiring."],"exampleFix":"// before\n// in an observer, called from a queue worker with no DB transaction\nDB::connection()->afterCommit(fn () => Cache::forget(\"user:{$user->id}\"));\n// after\nif (DB::connection()->transactionLevel() > 0) {\n    DB::connection()->afterCommit(fn () => Cache::forget(\"user:{$user->id}\"));\n} else {\n    Cache::forget(\"user:{$user->id}\");\n}","handlingStrategy":"validation","validationCode":"// Only register afterCommit callbacks when a transaction (and its manager) is active.\n$conn = DB::connection();\nif ($conn->transactionLevel() > 0) {\n    $conn->afterCommit($callback);\n} else {\n    // no transaction: run immediately, or dispatch a job\n    $callback();\n}","typeGuard":"function afterCommitIsSafe(\\Illuminate\\Database\\ConnectionInterface $conn): bool\n{\n    // The transactions manager is set whenever a transaction has been started.\n    return $conn instanceof \\Illuminate\\Database\\Connection && $conn->transactionLevel() > 0;\n}","tryCatchPattern":"try {\n    DB::connection()->afterCommit($callback);\n} catch (\\RuntimeException $e) {\n    if (str_contains($e->getMessage(), 'Transactions Manager has not been set')) {\n        // either open a transaction first, or run the callback directly\n        $callback();\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Use the framework's DB::transaction() helper so the manager is always initialized.","In observers/listeners that may run from queue workers or CLI, guard afterCommit with transactionLevel().","Prefer dispatching a job over afterCommit when the side effect must run regardless of transaction state."],"tags":["database","transactions","after-commit","configuration"],"backgroundTag":null,"analyzedSha":"e0f6eb3518ac29fbbca8529e97d0df7fc9f24481","analyzedAt":"2026-08-11T20:52:37.562Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}