kubernetes/kops · error
failed to list domains: %s
Error message
failed to list domains: %s
What it means
Wraps any error from the DigitalOcean godo DomainService().List API call during DNS resource discovery in kops' digitalocean destroy/listDns flow. It indicates the cloud API listing of domains failed before kOps could match the cluster name to a domain. The underlying DO API error is embedded in the message.
Source
Thrown at pkg/resources/digitalocean/resources.go:145
var blocks []string
for _, dropletID := range volume.DropletIDs {
blocks = append(blocks, "droplet:"+strconv.Itoa(dropletID))
}
resourceTracker.Blocks = blocks
resourceTrackers = append(resourceTrackers, resourceTracker)
}
}
return resourceTrackers, nil
}
func listDNS(cloud fi.Cloud, clusterName string) ([]*resources.Resource, error) {
c := cloud.(do.DOCloud)
domains, _, err := c.DomainService().List(context.TODO(), &godo.ListOptions{})
if err != nil {
return nil, fmt.Errorf("failed to list domains: %s", err)
}
var domainName string
for _, domain := range domains {
if strings.HasSuffix(clusterName, domain.Name) {
domainName = domain.Name
}
}
if domainName == "" {
return nil, fmt.Errorf("failed to find domain for cluster: %s", clusterName)
}
records, err := getAllRecordsByDomain(c, domainName)
if err != nil {
return nil, fmt.Errorf("failed to list records for domain %s: %s", domainName, err)
}
View on GitHub (pinned to 4c8573c808)
Solutions
- Verify the DO API token is valid and has domain read scope (doctl auth init / check DIGITALOCEAN_ACCESS_TOKEN)
- Retry the operation; transient API/network failures are common
- Check https://www.digitaloceanstatus.com for API outages
- Inspect the wrapped error in the message for 401/403/429 and address accordingly
Example fix
// before kops delete cluster --name my.cluster --cloud digitalocean # fails with API error // after export DIGITALOCEAN_ACCESS_TOKEN=<valid token with domain read scope> kops delete cluster --name my.cluster --cloud digitalocean
Defensive patterns
Strategy: try-catch
Validate before calling
func validateDOToken(token string) error {
if token == "" { return errors.New("DIGITALOCEAN_ACCESS_TOKEN not set") }
client := godo.NewFromToken(token)
_, _, err := client.Domains.List(context.TODO(), &godo.ListOptions{PerPage: 1})
return err
} Type guard
func isAuthError(err error) bool {
return strings.Contains(err.Error(), "401") || strings.Contains(err.Error(), "403")
} Try / catch
domains, _, err := c.DomainService().List(ctx, &godo.ListOptions{})
if err != nil {
if isRateLimit(err) { /* backoff and retry */ }
return fmt.Errorf("failed to list domains: %s", err)
} Prevention
- Verify token validity with `doctl account get` before running kops
- Use a token with at least domain read scope
- Retry with exponential backoff for transient API errors
- Monitor DO status page during teardown
When it happens
Trigger: c.DomainService().List(context.TODO(), &godo.ListOptions{}) returns an error: invalid/expired DO API token, network failure, DO API outage, or rate limiting (429).
Common situations: Expired or misscoped DIGITALOCEAN_ACCESS_TOKEN (token lacking 'read' scope on domains), corporate proxy blocking api.digitalocean.com, or transient DO API 5xx during cluster deletion.
Related errors
- failed to apply resource record set: %s, err: %s
- failed to delete record: %v
- failed to find domain for cluster: %s
- failed to list records for domain %s: %s
- failed to delete record for domain %s: %d
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/c9186b1b717e5b4c.
Report an issue: GitHub.