coollabsio/coolify · error · RuntimeException
No DigitalOcean token found for the server team.
Error message
No DigitalOcean token found for the server team.
What it means
DigitalOcean twin of the Vultr error: DeleteServer::deleteFromDigitalOceanById() throws this RuntimeException when deleteFromDigitalOcean=true (or the server has digitalocean_droplet_id with provider deletion enabled) and no CloudProviderToken with provider='digitalocean' can be resolved — first via the passed cloudProviderTokenId, then via any team-owned DigitalOcean token. The catch block logs and re-throws, so the Coolify-side server deletion (forceDelete) never runs.
Source
Thrown at app/Actions/Server/DeleteServer.php:165
{
try {
$token = null;
if ($cloudProviderTokenId) {
$token = CloudProviderToken::where('id', $cloudProviderTokenId)
->where('team_id', $teamId)
->where('provider', 'digitalocean')
->first();
}
if (! $token) {
$token = CloudProviderToken::where('team_id', $teamId)
->where('provider', 'digitalocean')
->first();
}
if (! $token) {
throw new \RuntimeException('No DigitalOcean token found for the server team.');
}
$digitalOceanService = new DigitalOceanService($token->token);
$digitalOceanService->deleteDroplet($digitalOceanDropletId);
logger()->debug('Deleted droplet from DigitalOcean', [
'digitalocean_droplet_id' => $digitalOceanDropletId,
'team_id' => $teamId,
]);
} catch (\Throwable $e) {
logger()->error('Failed to delete droplet from DigitalOcean', [
'error' => $e->getMessage(),
'digitalocean_droplet_id' => $digitalOceanDropletId,
'team_id' => $teamId,
]);
throw $e;
}View on GitHub (pinned to 70b9acc424)
Solutions
- Re-add a DigitalOcean provider token for the server's team so the fallback token lookup succeeds.
- Pass an explicit, valid cloudProviderTokenId (provider='digitalocean', matching team_id) when dispatching DeleteServer.
- If the droplet was already destroyed manually, delete the server without deleteFromDigitalOcean.
- Programmatically: catch the RuntimeException (log + notify) and continue Coolify-side deletion if provider cleanup is best-effort.
Example fix
// before
DeleteServer::run($serverId, deleteFromDigitalOcean: true,
digitalOceanDropletId: $server->digitalocean_droplet_id);
// after
$hasToken = CloudProviderToken::where('team_id', $server->team_id)
->where('provider', 'digitalocean')->exists();
DeleteServer::run($serverId,
deleteFromDigitalOcean: $hasToken,
digitalOceanDropletId: $server->digitalocean_droplet_id); Defensive patterns
Strategy: validation
Validate before calling
$hasDoToken = \App\Models\CloudProviderToken::query()
->where('team_id', $server->team_id)
->where('provider', 'digitalocean')
->exists();
if (! $hasDoToken) {
return back()->withErrors(['server' => 'Add a DigitalOcean token for this team before deleting the server from DigitalOcean.']);
}
\App\Actions\Server\DeleteServer::run($server->id, deleteFromDigitalOcean: true, digitalOceanDropletId: $server->digitalocean_droplet_id); Type guard
function teamHasDigitalOceanToken(int $teamId): bool
{
return \App\Models\CloudProviderToken::query()
->where('team_id', $teamId)
->where('provider', 'digitalocean')
->exists();
} Try / catch
try {
DeleteServer::run($serverId, deleteFromDigitalOcean: true, digitalOceanDropletId: $dropletId);
} catch (\RuntimeException $e) {
if (str_contains($e->getMessage(), 'No DigitalOcean token found')) {
report($e); // ask user to re-link token; do not auto-retry
} else {
throw $e;
}
} Prevention
- Maintain a DigitalOcean token per team that owns DO-linked servers.
- Pass cloudProviderTokenId explicitly in automated deletion flows.
- Disable the 'delete from provider' option in the UI when the team lacks a matching token.
- Watch the logs: the action logs 'Failed to delete droplet from DigitalOcean' before re-throwing — monitor that channel.
When it happens
Trigger: Deleting a DigitalOcean-linked server when the team's DO token was deleted, when cloudProviderTokenId references a token of the wrong provider or wrong team, or when the server row's team_id differs from the token owner after re-organization.
Common situations: DO token rotated/deleted after droplet creation; multiple teams where the token lives in another team; API automation passing deleteFromDigitalOcean without a token id.
Related errors
- No Vultr token found for the server team.
- You do not have permission to create tokens with root permis
- You do not have permission to create tokens with write permi
- You do not have permission to create tokens with deploy perm
- You do not have permission to create tokens with read:sensit
AI-assisted analysis of coollabsio/coolify@70b9acc424 (2026-08-17).
Data as JSON: /api/errors/f15803157b9bba20.
Report an issue: GitHub.