diff --git a/app/client/modules/backups/components/schedule-summary.tsx b/app/client/modules/backups/components/schedule-summary.tsx
index 8bdd3b9d..87efda27 100644
--- a/app/client/modules/backups/components/schedule-summary.tsx
+++ b/app/client/modules/backups/components/schedule-summary.tsx
@@ -181,7 +181,8 @@ export const ScheduleSummary = (props: Props) => {
Warning Details
- Last backup completed with warnings. Check your container logs for more details.
+ {schedule.lastBackupError ??
+ "Last backup completed with warnings. Check your container logs for more details."}
)}
diff --git a/app/server/modules/backups/backups.service.ts b/app/server/modules/backups/backups.service.ts
index f8dc2837..120dc7cc 100644
--- a/app/server/modules/backups/backups.service.ts
+++ b/app/server/modules/backups/backups.service.ts
@@ -431,23 +431,25 @@ const stopBackup = async (scheduleId: number) => {
throw new NotFoundError("Backup schedule not found");
}
- const abortController = runningBackups.get(scheduleId);
- if (!abortController) {
- throw new ConflictError("No backup is currently running for this schedule");
+ try {
+ const abortController = runningBackups.get(scheduleId);
+ if (!abortController) {
+ throw new ConflictError("No backup is currently running for this schedule");
+ }
+
+ logger.info(`Stopping backup for schedule ${scheduleId}`);
+
+ abortController.abort();
+ } finally {
+ await db
+ .update(backupSchedulesTable)
+ .set({
+ lastBackupStatus: "warning",
+ lastBackupError: "Backup was stopped by user",
+ updatedAt: Date.now(),
+ })
+ .where(eq(backupSchedulesTable.id, scheduleId));
}
-
- logger.info(`Stopping backup for schedule ${scheduleId}`);
-
- abortController.abort();
-
- await db
- .update(backupSchedulesTable)
- .set({
- lastBackupStatus: "warning",
- lastBackupError: "Backup was stopped by user",
- updatedAt: Date.now(),
- })
- .where(eq(backupSchedulesTable.id, scheduleId));
};
const runForget = async (scheduleId: number, repositoryId?: string) => {
diff --git a/app/server/modules/lifecycle/startup.ts b/app/server/modules/lifecycle/startup.ts
index 2761bf88..1bf3265a 100644
--- a/app/server/modules/lifecycle/startup.ts
+++ b/app/server/modules/lifecycle/startup.ts
@@ -1,7 +1,7 @@
import { Scheduler } from "../../core/scheduler";
import { and, eq, or } from "drizzle-orm";
import { db } from "../../db/db";
-import { volumesTable } from "../../db/schema";
+import { backupSchedulesTable, volumesTable } from "../../db/schema";
import { logger } from "../../utils/logger";
import { restic } from "../../utils/restic";
import { volumeService } from "../volumes/volume.service";
@@ -63,6 +63,18 @@ export const startup = async () => {
});
}
+ await db
+ .update(backupSchedulesTable)
+ .set({
+ lastBackupStatus: "warning",
+ lastBackupError: "Zerobyte was restarted during the last scheduled backup",
+ updatedAt: Date.now(),
+ })
+ .where(eq(backupSchedulesTable.lastBackupStatus, "in_progress"))
+ .catch((err) => {
+ logger.error(`Failed to update stuck backup schedules on startup: ${err.message}`);
+ });
+
Scheduler.build(CleanupDanglingMountsJob).schedule("0 * * * *");
Scheduler.build(VolumeHealthCheckJob).schedule("*/30 * * * *");
Scheduler.build(RepositoryHealthCheckJob).schedule("50 12 * * *");