{"record":{"id":"9ce2126dd89fdcba","repo":"kubernetes/kops","slug":"droplet-d-has-unexpected-status-q","errorCode":null,"errorMessage":"droplet %d has unexpected status %q","messagePattern":"droplet (.+?) has unexpected status %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/nodeidentity/do/identify.go","lineNumber":156,"sourceCode":"\t\t} else if exists {\n\t\t\treturn obj.(*nodeidentity.Info), nil\n\t\t}\n\t}\n\n\tdropletID, err := strconv.Atoi(instanceID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to convert provider ID number %q: %s\", instanceID, err)\n\t}\n\n\tdroplet, _, err := i.doClient.Droplets.Get(ctx, dropletID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to retrieve droplet %d: %w\", dropletID, err)\n\t}\n\tif droplet == nil {\n\t\treturn nil, fmt.Errorf(\"droplet %d not found\", dropletID)\n\t}\n\tif droplet.Status != \"active\" && droplet.Status != \"new\" {\n\t\treturn nil, fmt.Errorf(\"droplet %d has unexpected status %q\", dropletID, droplet.Status)\n\t}\n\n\tinfo := &nodeidentity.Info{\n\t\tInstanceID: instanceID,\n\t\tLabels:     labelsFromTags(droplet.Tags),\n\t}\n\n\tif i.cacheEnabled {\n\t\tif err := i.cache.Add(info); err != nil {\n\t\t\tklog.Warningf(\"Failed to add node identity info to cache: %v\", err)\n\t\t}\n\t}\n\n\treturn info, nil\n}\n\n// labelsFromTags derives node labels from a droplet's tags.\n//","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/nodeidentity/do/identify.go#L138-L174","documentation":"The droplet was found but its status is neither 'active' nor 'new'. IdentifyNode only accepts droplets that are usable or still provisioning; intermediate states (off, archive, etc.) are rejected because the node identity cannot be trusted for a non-running droplet.","triggerScenarios":"Droplet.Status is e.g. 'off' after a shutdown/power-cycle, or another transitional state when the node identity lookup runs.","commonSituations":"Droplet powered off manually or via autoscaling/reschedule; droplet stuck in a transitional state after a failed resize or snapshot restore; node object outliving a powered-down machine.","solutions":["Power the droplet back on (doctl compute droplet-action poweron <id> or via the console) so its status becomes 'active'","Wait for any in-progress action (resize/restore/rebuild) to finish and the status to settle to 'active'","Check droplet action history for failed operations leaving it in an odd state","If the machine is permanently decommissioned, remove the stale Node from the cluster"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"if droplet.Status != \"active\" && droplet.Status != \"new\" {\n    return fmt.Errorf(\"droplet not ready: %s\", droplet.Status)\n}","typeGuard":"func dropletUsable(d *godo.Droplet) bool {\n    return d != nil && (d.Status == \"active\" || d.Status == \"new\")\n}","tryCatchPattern":"info, err := IdentifyNode(ctx, providerID)\nif err != nil {\n    if strings.Contains(err.Error(), \"unexpected status\") {\n        // power on the droplet or wait for its action to complete, then retry\n    }\n}","preventionTips":["Avoid power-off actions while node identity is needed","Wait for droplet actions (resize/restore) to complete before reconciling","Alert on droplets stuck in non-active states","Clean up Nodes for decommissioned/powered-off droplets"],"tags":["digitalocean","droplet","status","lifecycle"],"backgroundTag":"droplet-unexpected-status","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}