{"record":{"id":"e783afe3873e3d27","repo":"kubernetes/kops","slug":"failed-to-delete-server-q-w","errorCode":null,"errorMessage":"failed to delete server %q: %w","messagePattern":"failed to delete server %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/hetzner/cloud.go","lineNumber":288,"sourceCode":"\t\treturn fmt.Errorf(\"failed to stop server %q: %w\", strconv.FormatInt(id, 10), err)\n\t}\n\n\tfor i := 1; i <= 30; i++ {\n\t\tserver, _, err := client.GetByID(ctx, id)\n\t\tif err != nil || server == nil {\n\t\t\treturn fmt.Errorf(\"failed to get info for server %q: %w\", strconv.FormatInt(id, 10), err)\n\t\t}\n\n\t\tif server.Status == hcloud.ServerStatusOff {\n\t\t\tbreak\n\t\t}\n\n\t\ttime.Sleep(time.Second * 5)\n\t}\n\n\t_, err = client.Delete(ctx, server)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to delete server %q: %w\", strconv.FormatInt(id, 10), err)\n\t}\n\n\treturn nil\n}\n\nfunc (c *hetznerCloudImplementation) DetachInstance(instance *cloudinstances.CloudInstance) error {\n\t// Hetzner Cloud API doesn't provide the option of using cloud groups\n\treturn nil\n}\n\n// ProviderID returns the kOps API identifier for Hetzner Cloud\nfunc (c *hetznerCloudImplementation) ProviderID() kops.CloudProviderID {\n\treturn kops.CloudProviderHetzner\n}\n\n// Region returns the Hetzner Cloud region\nfunc (c *hetznerCloudImplementation) Region() string {\n\treturn c.region","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/hetzner/cloud.go#L270-L306","documentation":"Fires in deleteServer after the Hetzner hcloud API Delete call on an already-powered-off server returns an error. It wraps the underlying API failure (rate limit, auth, server not found, or server still running) so instance-deletion tasks surface why the Hetzner server could not be removed.","triggerScenarios":"Calling DeleteInstance/DeleteGroup when the server was already deleted (404 not_found), the token lacks delete permission, delete is blocked (e.g. protected server or attached primary IP/volume with delete protection), or transient API errors.","commonSituations":"Concurrent deletion by another kOps run or manual console deletion; servers with delete protection enabled; Hetzner API outages right after shutdown completes.","solutions":["Check if the server still exists; treat not_found as success and reconcile state","Disable delete protection on the server (and its attached volumes/primary IPs) in Hetzner console or API","Ensure the token has write permissions and no other process is deleting the server concurrently","Retry the delete on transient errors"],"exampleFix":"// before\nif err != nil {\n\treturn fmt.Errorf(\"failed to delete server %q: %w\", strconv.FormatInt(id, 10), err)\n}\n// after\nif err != nil {\n\tif hcloud.IsError(err, hcloud.ErrorCodeNotFound) {\n\t\treturn nil // already deleted elsewhere\n\t}\n\treturn fmt.Errorf(\"failed to delete server %q: %w\", strconv.FormatInt(id, 10), err)\n}","handlingStrategy":"type-guard","validationCode":"server, _, err := client.GetByID(ctx, id)\nif server == nil {\n\treturn nil // already deleted; no Delete call needed\n}\nif server.Protection.Delete {\n\treturn fmt.Errorf(\"server %d has delete protection enabled\", id)\n}","typeGuard":"var hcloudErr *hcloud.Error\nif errors.As(err, &hcloudErr) && hcloudErr.Code == hcloud.ErrorCodeNotFound {\n\t// treat as success: already deleted\n}","tryCatchPattern":"_, err = client.Delete(ctx, server)\nif err != nil {\n\tvar hErr *hcloud.Error\n\tif errors.As(err, &hErr) && hErr.Code == hcloud.ErrorCodeNotFound {\n\t\treturn nil\n\t}\n\treturn fmt.Errorf(\"failed to delete server %q: %w\", strconv.FormatInt(id, 10), err)\n}","preventionTips":["Check server.Protection.Delete before deleting; disable protection first","Treat not_found as successful deletion to stay idempotent","Verify token write permissions","Avoid concurrent deletions of the same server"],"tags":["hetzner","api","server","delete"],"backgroundTag":"hetzner-api-request-failed","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"}