{"record":{"id":"a492d1777746fb83","repo":"kubernetes/kops","slug":"failed-to-convert-droplet-id-to-int-s-a492d1","errorCode":null,"errorMessage":"failed to convert droplet ID to int: %s","messagePattern":"failed to convert droplet ID to int: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/do/cloud.go","lineNumber":136,"sourceCode":"\treturn getCloudGroups(c, cluster, instancegroups, warnUnmatched, nodes)\n}\n\n// DeleteGroup is not implemented yet, is a func that needs to delete a DO instance group.\nfunc (c *doCloudImplementation) DeleteGroup(g *cloudinstances.CloudInstanceGroup) error {\n\tklog.V(8).Info(\"digitalocean cloud provider DeleteGroup not implemented yet\")\n\treturn fmt.Errorf(\"digital ocean cloud provider does not support deleting cloud groups at this time\")\n}\n\n// DeregisterInstance drains a cloud instance and loadbalancers.\nfunc (c *doCloudImplementation) DeregisterInstance(i *cloudinstances.CloudInstance) error {\n\tklog.V(8).Info(\"DO DeregisterInstance not implemented\")\n\treturn nil\n}\n\nfunc (c *doCloudImplementation) DeleteInstance(i *cloudinstances.CloudInstance) error {\n\tdropletID, err := strconv.Atoi(i.ID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to convert droplet ID to int: %s\", err)\n\t}\n\n\t_, _, err = c.Client.DropletActions.Shutdown(context.TODO(), dropletID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error stopping instance %d: %v\", dropletID, err)\n\t}\n\n\t// Wait for 5 min to stop the instance\n\tfor i := 0; i < 5; i++ {\n\t\tdroplet, _, err := c.Client.Droplets.Get(context.TODO(), dropletID)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error describing instance %d: %v\", dropletID, err)\n\t\t}\n\n\t\tklog.V(8).Infof(\"stopping DO instance %q, current Status: %q\", droplet, droplet.Status)\n\n\t\tif droplet.Status == \"off\" {\n\t\t\tbreak","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/do/cloud.go#L118-L154","documentation":"DeleteInstance on DigitalOcean converts the CloudInstanceGroup member's string ID to an int with strconv.Atoi because the DO API takes a numeric droplet ID. If the ID is not a valid integer, kOps wraps the parse error with 'failed to convert droplet ID to int'. This indicates the instance record is corrupted or was constructed from a non-droplet entity.","triggerScenarios":"Calling `kops delete instance` / rolling-update delete paths on a DO cluster where the CloudInstance.ID is empty, blank, or non-numeric (e.g. placeholder IDs from mis-parsed droplet lists or control-plane entries without real droplet backing).","commonSituations":"Stale kops state referencing deleted droplets; group membership built from nodes registered in k8s whose IDs are not droplet IDs; state-store corruption after manual droplet deletion.","solutions":["Inspect the instance in `kops get instancegroups` / cloud state; find the member whose ID is not numeric","Run `kops update cluster --yes` (or `kops rolling-update cluster --cloud digitalocean --force`) to refresh cloud state from the DO API","Remove the stale member from the InstanceGroup spec in the state store and re-run update","Verify droplets exist in the DO project matching the cluster tag"],"exampleFix":"// before\n# CloudInstance.ID = \"\" (stale member)\n// after\nkops update cluster --name cluster.example.com --yes   # rebuilds group from live droplets\n# or edit spec to drop the stale member:\nkops edit instancegroup nodes --name cluster.example.com","handlingStrategy":"validation","validationCode":"if id, err := strconv.Atoi(i.ID); err != nil || id <= 0 {\n    return fmt.Errorf(\"instance %q has invalid droplet ID; refresh cloud state first\", i.ID)\n}","typeGuard":null,"tryCatchPattern":"dropletID, err := strconv.Atoi(i.ID)\nif err != nil {\n    return fmt.Errorf(\"skipping instance with non-numeric ID %q: %w\", i.ID, err)\n}","preventionTips":["Refresh kOps cloud state (kops update cluster) before deleting instances","Never reference instances from stale state after manual droplet deletion","Validate instance IDs in `kops get` output before scripting deletes","Keep kops as the single writer to droplet lifecycle"],"tags":["digitalocean","instance-groups","data-corruption"],"backgroundTag":"invalid-instance-id","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}