laravel/framework · error · RuntimeException
Transactions Manager has not been set.
Error message
Transactions Manager has not been set.
What it means
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.
Source
Thrown at src/Illuminate/Database/Concerns/ManagesTransactions.php:360
{
return $this->transactions;
}
/**
* Execute the callback after a transaction commits.
*
* @param callable $callback
* @return void
*
* @throws \RuntimeException
*/
public function afterCommit($callback)
{
if ($this->transactionsManager) {
return $this->transactionsManager->addCallback($callback);
}
throw new RuntimeException('Transactions Manager has not been set.');
}
/**
* Execute the callback after a transaction rolls back.
*
* @param callable $callback
* @return void
*
* @throws \RuntimeException
*/
public function afterRollBack($callback)
{
if ($this->transactionsManager) {
return $this->transactionsManager->addCallbackForRollback($callback);
}
throw new RuntimeException('Transactions Manager has not been set.');
}View on GitHub (pinned to bd6b5437e6)
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.
Example fix
// before $conn = new Illuminate\Database\MySqlConnection($pdo, '', ''); $conn->afterCommit(fn () => event(new OrderShipped)); // throws 'Transactions Manager has not been set.' // after $conn = DB::connection(); // manager wired by framework $conn->afterCommit(fn () => event(new OrderShipped));
Defensive patterns
Strategy: validation
Validate before calling
$conn = DB::connection();
if (! $conn->getTransactionManager()) {
// manager missing; fire callback immediately or wire the manager
$cb();
return;
}
$conn->afterCommit($cb); Type guard
function connectionHasTransactionManager(\Illuminate\Database\Connection $c): bool
{
return method_exists($c, 'getTransactionManager') && $c->getTransactionManager() !== null;
} Try / catch
try {
DB::afterCommit($cb);
} catch (\RuntimeException $e) {
if (str_contains($e->getMessage(), 'Transactions Manager has not been set')) {
$cb(); // fire immediately when outside framework
} else throw $e;
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Method [run] missing from {class}
- Callback must be a callable, callback array, or a 'Class@met
- Auth guard [{$name}] is not defined.
- Auth driver [{$config['driver']}] for guard [{$name}] is not
- Authentication user provider [{$driver}] is not defined.
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/c24ecb7682619974.json.
Report an issue: GitHub.