@bernard123 In Laravel, DB::transaction() only rolls back if an uncaught exception happens inside it.
But when you throw ValidationException, Laravel catches it internally to return a validation error response (like 422), so it doesn’t treat it like a crash. That’s why the rollback doesn’t happen.
If you really want it to rollback on validation errors, you should manually use DB::beginTransaction() and DB::rollBack() inside a try-catch. That gives you full control. as the @jayandholariya has suggested
and If you must use DB::transaction() and want validation errors to trigger rollback then :
try {
DB::transaction(function() {
User::create([...]);
// Throw validation error inside:
throw ValidationException::withMessages([
'name' => 'This field is required.'
]);
});
} catch (ValidationException $e) {
// The rollback has already happened ✅
return back()->withErrors($e->errors());
}