{"record":{"id":"0120790ebeaeaec1","repo":"coollabsio/coolify","slug":"the-s3-storage-is-unavailable","errorCode":null,"errorMessage":"The S3 storage is unavailable.","messagePattern":"The S3 storage is unavailable\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"app/Livewire/Project/Shared/Storages/VolumeBackups.php","lineNumber":308,"sourceCode":"        if ($execution->status === 'running' || $execution->stop_recovery_pending || $execution->s3_cleanup_pending) {\n            $this->dispatch('error', 'Wait for the backup and recovery operations to finish before deleting it.');\n\n            return false;\n        }\n\n        try {\n            $server = $this->backup->server();\n            if (! $execution->local_storage_deleted && filled($execution->filename)) {\n                if (! $server) {\n                    throw new \\RuntimeException('The server is unavailable.');\n                }\n\n                deleteBackupsLocally($execution->filename, $server, throwError: true);\n            }\n\n            if ($this->delete_backup_s3 && $execution->s3_uploaded && ! $execution->s3_storage_deleted) {\n                if (! $execution->s3) {\n                    throw new \\RuntimeException('The S3 storage is unavailable.');\n                }\n\n                deleteBackupsS3($execution->filename, $execution->s3);\n            }\n\n            $execution->delete();\n            $this->delete_backup_s3 = false;\n            $this->dispatch('success', 'Backup deleted.');\n\n            return true;\n        } catch (Throwable $exception) {\n            $this->dispatch('error', 'Failed to delete backup: '.$exception->getMessage());\n\n            return false;\n        }\n    }\n\n    public function render()","sourceCodeStart":290,"sourceCodeEnd":326,"githubUrl":"https://github.com/coollabsio/coolify/blob/70b9acc42467278373e00de77abb40684e25b395/app/Livewire/Project/Shared/Storages/VolumeBackups.php#L290-L326","documentation":"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.","triggerScenarios":"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.","commonSituations":"Rotating or cleaning up S3 storages without first purging their backup executions; stale UI checkbox after the storage was removed elsewhere; multi-team handovers.","solutions":["Untick 'delete from S3' if the bucket/objects were already removed manually, then delete the execution","Re-create an S3 storage matching the old credentials/bucket so the relation resolves, then retry","Delete the objects in the bucket yourself, set execution->s3_storage_deleted = true, and delete the execution","Check execution->storage_id / the s3 relation to see which storage row is missing"],"exampleFix":"// before\nif ($this->delete_backup_s3 && $execution->s3_uploaded) {\n    deleteBackupsS3($execution->filename, $execution->s3);\n}\n\n// after\nif ($this->delete_backup_s3 && $execution->s3_uploaded) {\n    if (! $execution->s3) {\n        $this->delete_backup_s3 = false;\n        $this->dispatch('error', 'S3 storage was removed; delete bucket objects manually.');\n    } else {\n        deleteBackupsS3($execution->filename, $execution->s3);\n    }\n}","handlingStrategy":"validation","validationCode":"if ($this->delete_backup_s3 && $execution->s3_uploaded && ! $execution->s3) {\n    $this->delete_backup_s3 = false; // storage gone; skip S3 leg\n    // notify user to clean the bucket manually\n}","typeGuard":"/** @param mixed $execution */\nfunction executionHasS3Storage($execution): bool\n{\n    return $execution?->s3 !== null;\n}","tryCatchPattern":"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.","preventionTips":["Purge or reassign backup executions before deleting an S3 storage","Untick 'delete from S3' when the storage was already removed","Clean buckets manually and set s3_storage_deleted when credentials are gone"],"tags":["backup","s3","storage","deletion"],"backgroundTag":"missing-related-resource","analyzedSha":"70b9acc42467278373e00de77abb40684e25b395","analyzedAt":"2026-08-17T01:41:01.313Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}