{"record":{"id":"ac62751b162d6031","repo":"kubernetes/kops","slug":"droplet-d-not-found","errorCode":null,"errorMessage":"droplet %d not found","messagePattern":"droplet (.+?) not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/nodeidentity/do/identify.go","lineNumber":153,"sourceCode":"\tif i.cacheEnabled {\n\t\tif obj, exists, err := i.cache.GetByKey(instanceID); err != nil {\n\t\t\tklog.Warningf(\"Nodeidentity info cache lookup failure: %v\", err)\n\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}","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/nodeidentity/do/identify.go#L135-L171","documentation":"The DigitalOcean API returned success but a nil droplet object, meaning no droplet with the given numeric ID exists in the account. IdentifyNode treats this as a hard error since a valid node must map to an existing droplet.","triggerScenarios":"i.doClient.Droplets.Get succeeds but returns (nil, resp, nil) — the droplet ID in providerID does not correspond to any droplet in the token's team/context.","commonSituations":"Stale providerID after droplet deletion; API token scoped to a different team than the one owning the droplet; typo in the numeric ID; droplet recreated with a new ID after rebuild.","solutions":["Confirm the droplet ID exists via `doctl compute droplet get <id>`","Check the API token belongs to the team/account that owns the droplet","If the droplet was deleted, delete the stale Node resource or reprovision the machine","Re-verify the providerID on the Node matches the current droplet's numeric ID"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// pre-check the droplet exists\ndroplet, _, err := client.Droplets.Get(ctx, id)\nif err != nil || droplet == nil {\n    return fmt.Errorf(\"droplet %d does not exist in this team\", id)\n}","typeGuard":null,"tryCatchPattern":"info, err := IdentifyNode(ctx, providerID)\nif err != nil {\n    if strings.Contains(err.Error(), \"not found\") {\n        // droplet gone: delete the Node or reprovision\n    }\n}","preventionTips":["Keep API token scoped to the team that owns the droplets","Reconcile Node objects against the DO API to drop stale entries","Confirm droplet IDs after rebuilds — new droplets get new IDs","Use doctl to cross-check existence before identity lookups"],"tags":["digitalocean","droplet","not-found","api"],"backgroundTag":"resource-not-found","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"}