diff --git a/app/Services/ImportProcessor.php b/app/Services/ImportProcessor.php index 7b371b7..7bc7eb3 100644 --- a/app/Services/ImportProcessor.php +++ b/app/Services/ImportProcessor.php @@ -1068,13 +1068,33 @@ public function process(Import $import, ?Authenticatable $user = null): array } } } catch (\Throwable $e) { + $rollbackFailed = false; + $rollbackError = null; if ($isPg) { // Roll back only this row's work try { DB::statement('ROLLBACK TO SAVEPOINT import_row_'.$rowNum); - } catch (\Throwable $ignored) { /* noop */ + } catch (\Throwable $ignored) { + $rollbackFailed = true; + $rollbackError = $ignored; } } + if ($rollbackFailed) { + // Abort the whole import if we cannot rollback to the row savepoint (transaction is poisoned) + ImportEvent::create([ + 'import_id' => $import->id, + 'user_id' => $user?->getAuthIdentifier(), + 'event' => 'row_rollback_failed', + 'level' => 'error', + 'message' => 'Rollback to savepoint failed; aborting import.', + 'context' => [ + 'row_number' => $rowNum, + 'exception' => $this->exceptionContext($rollbackError ?? $e), + ], + ]); + + throw $rollbackError ?? $e; + } // Ensure importRow exists for logging if failure happened before its creation if (! $importRow) { try {