coollabsio/coolify · error · RuntimeException

The server is unavailable, so local backup archives cannot…

Error message

The server is unavailable, so local backup archives cannot be deleted.

What it means

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.

Solutions

  1. Pass an explicit $server as the second argument to the action if the archives live on a server you can still address.
  2. 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.
  3. Restore/recreate the Server record with the same id so the relation resolves, then let the action clean up normally.

Example fix

// before: throws 'The server is unavailable...'
DeleteScheduledVolumeBackup::run($backup);

// after: guard for an orphaned schedule before calling
if ($backup->executions()->where('local_storage_deleted', false)->exists() && is_null($backup->server())) {
    // archives are unrecoverable-by-Coolify; decide explicitly
    $backup->executions()->update(['local_storage_deleted' => true]);
}
DeleteScheduledVolumeBackup::run($backup);
Defensive patterns

Strategy: validation

Validate before calling

// Verify the server relation exists whenever local archives are undeleted
$hasLocalArchives = $backup->executions()->where('local_storage_deleted', false)->exists();

if ($hasLocalArchives && is_null($backup->server())) {
    // decide explicitly: pass a known $server, or acknowledge losing the files
    // DeleteScheduledVolumeBackup::run($backup, $server);
}

Type guard

function scheduleIsDeletable(\App\Models\ScheduledVolumeBackup $backup): bool
{
    $needsServer = $backup->executions()->where('local_storage_deleted', false)->exists();

    return ! $needsServer || ! is_null($backup->server());
}

Try / catch

try {
    DeleteScheduledVolumeBackup::run($backup);
} catch (\RuntimeException $e) {
    if (str_contains($e->getMessage(), 'server is unavailable')) {
        // surface a choice: point at another server, or mark archives abandoned
        report('Orphaned volume backup schedule '.$backup->id.' — server record missing');
        return;
    }
    throw $e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of coollabsio/coolify@70b9acc424 (2026-08-17). Data as JSON: /api/errors/182f3e77954cc8cb. Report an issue: GitHub.

Appendix: source

Thrown at app/Actions/Shared/DeleteScheduledVolumeBackup.php:42

            if ($backup->executions()
                ->where(fn ($query) => $query
                    ->where('status', 'running')
                    ->orWhere('stop_recovery_pending', true)
                    ->orWhere('s3_cleanup_pending', true))
                ->exists()) {
                throw new \RuntimeException('Wait for the running storage backup and recovery operations to finish before deleting this schedule.');
            }

            $localFilenames = $backup->executions()
                ->where('local_storage_deleted', false)
                ->pluck('filename')
                ->filter()
                ->all();

            if ($localFilenames !== []) {
                $server ??= $backup->server();
                if (! $server) {
                    throw new \RuntimeException('The server is unavailable, so local backup archives cannot be deleted.');
                }

                deleteBackupsLocally($localFilenames, $server, throwError: true);
            }

            $s3Executions = $backup->executions()
                ->with('s3')
                ->where('s3_uploaded', true)
                ->where('s3_storage_deleted', false)
                ->get();

            foreach ($s3Executions->groupBy('s3_storage_id') as $executions) {
                $s3 = $executions->first()->s3;
                if (! $s3) {
                    throw new \RuntimeException('The S3 storage used by an existing backup is unavailable.');
                }

                $filenames = $executions->pluck('filename')->filter()->all();

View on GitHub (pinned to 70b9acc424)