kubernetes/kops · error
failed to retrieve droplet %d: %w
Error message
failed to retrieve droplet %d: %w
What it means
IdentifyNode calls doClient.Droplets.Get to fetch the droplet by numeric ID. If the DigitalOcean API returns an error (auth failure, rate limit, network error, or API-side not-found), the error is wrapped with the droplet ID using %w.
Source
Thrown at pkg/nodeidentity/do/identify.go:150
return nil, errors.New("provider ID number cannot be empty")
}
if i.cacheEnabled {
if obj, exists, err := i.cache.GetByKey(instanceID); err != nil {
klog.Warningf("Nodeidentity info cache lookup failure: %v", err)
} else if exists {
return obj.(*nodeidentity.Info), nil
}
}
dropletID, err := strconv.Atoi(instanceID)
if err != nil {
return nil, fmt.Errorf("failed to convert provider ID number %q: %s", instanceID, err)
}
droplet, _, err := i.doClient.Droplets.Get(ctx, dropletID)
if err != nil {
return nil, fmt.Errorf("failed to retrieve droplet %d: %w", dropletID, err)
}
if droplet == nil {
return nil, fmt.Errorf("droplet %d not found", dropletID)
}
if droplet.Status != "active" && droplet.Status != "new" {
return nil, fmt.Errorf("droplet %d has unexpected status %q", dropletID, droplet.Status)
}
info := &nodeidentity.Info{
InstanceID: instanceID,
Labels: labelsFromTags(droplet.Tags),
}
if i.cacheEnabled {
if err := i.cache.Add(info); err != nil {
klog.Warningf("Failed to add node identity info to cache: %v", err)
}
}View on GitHub (pinned to 4c8573c808)
Solutions
- Inspect the wrapped cause (%w) for the HTTP status — 401/403 means fix the API token, 429 means back off, 404 means the droplet is gone
- Verify the digitalocean token credential is valid and has read scope for droplets
- Check DigitalOcean API status and retry with backoff if rate-limited or during an outage
- If the droplet was deleted, remove the stale Node object from the cluster
Defensive patterns
Strategy: retry
Validate before calling
// verify credentials before calling
token := os.Getenv("DIGITALOCEAN_ACCESS_TOKEN")
if token == "" { return errors.New("missing DO token") } Try / catch
info, err := IdentifyNode(ctx, providerID)
if err != nil {
var apiErr *goauthorize.Error
if errors.As(err, &apiErr) {
switch {
case apiErr.StatusCode == 429: // backoff and retry
case apiErr.StatusCode == 401: // refresh/fix token
default: // alert on API outage
}
}
} Prevention
- Rotate and validate the DO API token regularly with droplet read scope
- Respect rate limits with backoff on 429
- Handle deleted droplets by cleaning up stale Node objects
- Monitor DigitalOcean API status in the controller's alerting
When it happens
Trigger: DigitalOcean API call fails: invalid/expired API token, rate limiting (429), network outage, or the droplet was deleted (404 surfaced by the API client as an error).
Common situations: Expired or revoked DO API token on the controller; DO API rate limits hit at scale; droplet deleted between providerID assignment and lookup; regional API outage.
Related errors
- droplet %d not found
- failed to list vpcs: %v
- LoadBalancers.List returned error: %v
- deleting droplets is not supported yet
- failed to get droplet region: %s
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/f95cb1614d440917.
Report an issue: GitHub.