kubernetes/kops · error
error stopping instance %d: %v
Error message
error stopping instance %d: %v
What it means
After parsing the droplet ID, DeleteInstance calls the DO DropletActions.Shutdown API to gracefully power off the droplet. If that API call fails, the error is wrapped as 'error stopping instance <id>'. The instance is not deleted and the rolling-delete flow aborts.
Source
Thrown at upup/pkg/fi/cloudup/do/cloud.go:141
klog.V(8).Info("digitalocean cloud provider DeleteGroup not implemented yet")
return fmt.Errorf("digital ocean cloud provider does not support deleting cloud groups at this time")
}
// DeregisterInstance drains a cloud instance and loadbalancers.
func (c *doCloudImplementation) DeregisterInstance(i *cloudinstances.CloudInstance) error {
klog.V(8).Info("DO DeregisterInstance not implemented")
return nil
}
func (c *doCloudImplementation) DeleteInstance(i *cloudinstances.CloudInstance) error {
dropletID, err := strconv.Atoi(i.ID)
if err != nil {
return fmt.Errorf("failed to convert droplet ID to int: %s", err)
}
_, _, err = c.Client.DropletActions.Shutdown(context.TODO(), dropletID)
if err != nil {
return fmt.Errorf("error stopping instance %d: %v", dropletID, err)
}
// Wait for 5 min to stop the instance
for i := 0; i < 5; i++ {
droplet, _, err := c.Client.Droplets.Get(context.TODO(), dropletID)
if err != nil {
return fmt.Errorf("error describing instance %d: %v", dropletID, err)
}
klog.V(8).Infof("stopping DO instance %q, current Status: %q", droplet, droplet.Status)
if droplet.Status == "off" {
break
}
if i == 5 {
return fmt.Errorf("fail to stop DO instance %v in 5 mins", dropletID)
}View on GitHub (pinned to 4c8573c808)
Solutions
- Verify the DO API token is valid and has write scope (doctl auth check / doctl compute droplet get <id>)
- Confirm the droplet still exists; if deleted manually, refresh kOps cloud state via `kops update cluster`
- Retry the rolling update — DO transient errors usually clear
- If the droplet is stuck, power it off via doctl then let kOps proceed
Example fix
// before export DIGITALOCEAN_ACCESS_TOKEN=expired_token // after export DIGITALOCEAN_ACCESS_TOKEN=<valid token with write scope> kops rolling-update cluster --name cluster.example.com --yes
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: token works and droplet exists
_, _, err := client.Droplets.Get(ctx, dropletID)
if err != nil {
return fmt.Errorf("droplet %d unreachable before shutdown: %w", dropletID, err)
} Try / catch
_, _, err := c.Client.DropletActions.Shutdown(ctx, dropletID)
if err != nil {
if gErr, ok := err.(godo.ErrorResponse); ok && gErr.Response.StatusCode == 404 {
return nil // already gone; treat as success
}
return fmt.Errorf("error stopping instance %d: %v", dropletID, err)
} Prevention
- Use a valid DO token with write scope for the whole operation
- Don't delete droplets manually while kOps operations run
- Retry on DO 5xx/rate-limit responses
- Check DO status page during large rolling updates
When it happens
Trigger: DropletActions.Shutdown returns an error during `kops delete instance`/rolling update on DO: droplet already powered off/deleted, DO API auth failure (invalid token), droplet ID no longer exists, or DO API 5xx/rate-limit response.
Common situations: Expired or revoked DigitalOcean API token; droplet deleted manually in the DO console while kOps tries to delete it; transient DO API outage.
Related errors
- error describing instance %d: %v
- failed to apply resource record set: %s, err: %s
- failed to list lbs: %v
- failed to delete droplet: %d, err: %s
- failed to delete VPC %s (ID %s): %s
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/d0c3f59194d6a93d.
Report an issue: GitHub.