{"record":{"id":"182f3e77954cc8cb","repo":"coollabsio/coolify","slug":"the-server-is-unavailable-so-local-backup-archive","errorCode":null,"errorMessage":"The server is unavailable, so local backup archives cannot be deleted.","messagePattern":"The server is unavailable, so local backup archives cannot be deleted\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"app/Actions/Shared/DeleteScheduledVolumeBackup.php","lineNumber":42,"sourceCode":"            if ($backup->executions()\n                ->where(fn ($query) => $query\n                    ->where('status', 'running')\n                    ->orWhere('stop_recovery_pending', true)\n                    ->orWhere('s3_cleanup_pending', true))\n                ->exists()) {\n                throw new \\RuntimeException('Wait for the running storage backup and recovery operations to finish before deleting this schedule.');\n            }\n\n            $localFilenames = $backup->executions()\n                ->where('local_storage_deleted', false)\n                ->pluck('filename')\n                ->filter()\n                ->all();\n\n            if ($localFilenames !== []) {\n                $server ??= $backup->server();\n                if (! $server) {\n                    throw new \\RuntimeException('The server is unavailable, so local backup archives cannot be deleted.');\n                }\n\n                deleteBackupsLocally($localFilenames, $server, throwError: true);\n            }\n\n            $s3Executions = $backup->executions()\n                ->with('s3')\n                ->where('s3_uploaded', true)\n                ->where('s3_storage_deleted', false)\n                ->get();\n\n            foreach ($s3Executions->groupBy('s3_storage_id') as $executions) {\n                $s3 = $executions->first()->s3;\n                if (! $s3) {\n                    throw new \\RuntimeException('The S3 storage used by an existing backup is unavailable.');\n                }\n\n                $filenames = $executions->pluck('filename')->filter()->all();","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/coollabsio/coolify/blob/70b9acc42467278373e00de77abb40684e25b395/app/Actions/Shared/DeleteScheduledVolumeBackup.php#L24-L60","documentation":"Thrown when the schedule has execution rows with local_storage_deleted=false (backup archives still on the destination server) but $backup->server() resolves to null. The Server record behind the schedule is gone, so deleteBackupsLocally() has no host to clean up on. This is a data-integrity guard so local archives are not orphaned silently.","triggerScenarios":"The Coolify Server record was deleted while a ScheduledVolumeBackup (or its executions with undeleted local files) still references it; the schedule outlived its server, so the relation returns null and undeleted local filenames exist.","commonSituations":"Team removes a decommissioned server from Coolify but forgets the volume backup schedules on it; database/server cleanup scripts delete servers without first deleting their backup schedules; restoring from a partial backup left orphaned schedules.","solutions":["Pass an explicit $server as the second argument to the action if the archives live on a server you can still address.","If the machine is truly gone, manually remove the orphaned archive files (or accept they stay), then mark those executions local_storage_deleted=true or delete the execution rows, and retry.","Restore/recreate the Server record with the same id so the relation resolves, then let the action clean up normally."],"exampleFix":"// before: throws 'The server is unavailable...'\nDeleteScheduledVolumeBackup::run($backup);\n\n// after: guard for an orphaned schedule before calling\nif ($backup->executions()->where('local_storage_deleted', false)->exists() && is_null($backup->server())) {\n    // archives are unrecoverable-by-Coolify; decide explicitly\n    $backup->executions()->update(['local_storage_deleted' => true]);\n}\nDeleteScheduledVolumeBackup::run($backup);","handlingStrategy":"validation","validationCode":"// Verify the server relation exists whenever local archives are undeleted\n$hasLocalArchives = $backup->executions()->where('local_storage_deleted', false)->exists();\n\nif ($hasLocalArchives && is_null($backup->server())) {\n    // decide explicitly: pass a known $server, or acknowledge losing the files\n    // DeleteScheduledVolumeBackup::run($backup, $server);\n}","typeGuard":"function scheduleIsDeletable(\\App\\Models\\ScheduledVolumeBackup $backup): bool\n{\n    $needsServer = $backup->executions()->where('local_storage_deleted', false)->exists();\n\n    return ! $needsServer || ! is_null($backup->server());\n}","tryCatchPattern":"try {\n    DeleteScheduledVolumeBackup::run($backup);\n} catch (\\RuntimeException $e) {\n    if (str_contains($e->getMessage(), 'server is unavailable')) {\n        // surface a choice: point at another server, or mark archives abandoned\n        report('Orphaned volume backup schedule '.$backup->id.' — server record missing');\n        return;\n    }\n    throw $e;\n}","preventionTips":["Delete a server's backup schedules before deleting the server in Coolify.","Include schedules in any server-deletion cleanup script (scheduled_volume_backups by server/database).","When passing $server explicitly, confirm SSH reachability first so local cleanup can actually run."],"tags":["backup","volume-backup","server","orphaned-record"],"backgroundTag":"orphaned-relation","analyzedSha":"70b9acc42467278373e00de77abb40684e25b395","analyzedAt":"2026-08-17T01:41:01.313Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}