coollabsio/coolify · error · RuntimeException

The S3 storage is unavailable.

Error message

The S3 storage is unavailable.

What it means

During the same delete flow: the execution reports s3_uploaded = true, the user ticked delete_backup_s3, s3_storage_deleted is false, but $execution->s3 (the S3 storage relation) is null. The S3 storage that received the upload was deleted from Coolify afterwards, so deleteBackupsS3() has no endpoint/credentials to target and the delete aborts.

Source

Thrown at app/Livewire/Project/Shared/Storages/VolumeBackups.php:308

        if ($execution->status === 'running' || $execution->stop_recovery_pending || $execution->s3_cleanup_pending) {
            $this->dispatch('error', 'Wait for the backup and recovery operations to finish before deleting it.');

            return false;
        }

        try {
            $server = $this->backup->server();
            if (! $execution->local_storage_deleted && filled($execution->filename)) {
                if (! $server) {
                    throw new \RuntimeException('The server is unavailable.');
                }

                deleteBackupsLocally($execution->filename, $server, throwError: true);
            }

            if ($this->delete_backup_s3 && $execution->s3_uploaded && ! $execution->s3_storage_deleted) {
                if (! $execution->s3) {
                    throw new \RuntimeException('The S3 storage is unavailable.');
                }

                deleteBackupsS3($execution->filename, $execution->s3);
            }

            $execution->delete();
            $this->delete_backup_s3 = false;
            $this->dispatch('success', 'Backup deleted.');

            return true;
        } catch (Throwable $exception) {
            $this->dispatch('error', 'Failed to delete backup: '.$exception->getMessage());

            return false;
        }
    }

    public function render()

View on GitHub (pinned to 70b9acc424)

Solutions

  1. Untick 'delete from S3' if the bucket/objects were already removed manually, then delete the execution
  2. Re-create an S3 storage matching the old credentials/bucket so the relation resolves, then retry
  3. Delete the objects in the bucket yourself, set execution->s3_storage_deleted = true, and delete the execution
  4. Check execution->storage_id / the s3 relation to see which storage row is missing

Example fix

// before
if ($this->delete_backup_s3 && $execution->s3_uploaded) {
    deleteBackupsS3($execution->filename, $execution->s3);
}

// after
if ($this->delete_backup_s3 && $execution->s3_uploaded) {
    if (! $execution->s3) {
        $this->delete_backup_s3 = false;
        $this->dispatch('error', 'S3 storage was removed; delete bucket objects manually.');
    } else {
        deleteBackupsS3($execution->filename, $execution->s3);
    }
}
Defensive patterns

Strategy: validation

Validate before calling

if ($this->delete_backup_s3 && $execution->s3_uploaded && ! $execution->s3) {
    $this->delete_backup_s3 = false; // storage gone; skip S3 leg
    // notify user to clean the bucket manually
}

Type guard

/** @param mixed $execution */
function executionHasS3Storage($execution): bool
{
    return $execution?->s3 !== null;
}

Try / catch

Catch Throwable, dispatch('error', ...) with the exception message; guard the S3 leg separately from the local leg so one missing storage does not block local cleanup.

Prevention

When it happens

Trigger: Deleting the S3 storage configuration from the team after executions were uploaded to it; a dangling storage_id on the execution; switching the backup to a new S3 storage while old executions point at the removed one.

Common situations: Rotating or cleaning up S3 storages without first purging their backup executions; stale UI checkbox after the storage was removed elsewhere; multi-team handovers.

Related errors


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