{"record":{"id":"07093c386440e097","repo":"kubernetes/kops","slug":"provider-id-number-cannot-be-empty","errorCode":null,"errorMessage":"provider ID number cannot be empty","messagePattern":"provider ID number cannot be empty","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/nodeidentity/do/identify.go","lineNumber":132,"sourceCode":"\n\treturn string(bodyBytes), nil\n}\n\n// IdentifyNode queries DigitalOcean for the node identity information.\nfunc (i *nodeIdentifier) IdentifyNode(ctx context.Context, node *corev1.Node) (*nodeidentity.Info, error) {\n\tproviderID := node.Spec.ProviderID\n\tif providerID == \"\" {\n\t\treturn nil, errors.New(\"provider ID cannot be empty\")\n\t}\n\n\tconst prefix = \"digitalocean://\"\n\tif !strings.HasPrefix(providerID, prefix) {\n\t\treturn nil, fmt.Errorf(\"provider ID %q is missing prefix %q\", providerID, prefix)\n\t}\n\n\tinstanceID := strings.TrimPrefix(providerID, prefix)\n\tif instanceID == \"\" {\n\t\treturn nil, errors.New(\"provider ID number cannot be empty\")\n\t}\n\n\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)","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/nodeidentity/do/identify.go#L114-L150","documentation":"Wraps a failure of the DescribeAutoScalingGroups paginator in FindAutoscalingGroups. After collecting candidate ASG names from tags, kOps pages through group details and re-verifies tags with matchesAsgTags (the tag filter is inexact). Any API page error is wrapped here.","triggerScenarios":"DescribeAutoScalingGroups NextPage fails: missing autoscaling:DescribeAutoScalingGroups permission, throttling on clusters with many ASGs, or regional endpoint/network failure.","commonSituations":"Large clusters with dozens of ASGs hitting AWS rate limits during rolling update; IAM role lacking describe permissions; stale credentials/expired session.","solutions":["Grant autoscaling:DescribeAutoScalingGroups to the kOps IAM role","Retry; throttling errors include request IDs and resolve with backoff","Confirm credentials with `aws sts get-caller-identity`","Run `aws autoscaling describe-auto-scaling-groups` manually to confirm access"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"_, err := client.DescribeAutoScalingGroups(ctx, &autoscaling.DescribeAutoScalingGroupsInput{MaxRecords: aws.Int32(1)})\nif err != nil { return fmt.Errorf(\"DescribeAutoScalingGroups unavailable: %w\", err) }","typeGuard":null,"tryCatchPattern":"err := cloud.GetCloudGroups(ctx, cluster, igs, true, nodes)\nif strings.Contains(err.Error(), \"error listing autoscaling groups\") {\n  if isAuthError(err) { refreshCredentials() } else { retryWithBackoff() }\n}","preventionTips":["Grant autoscaling:DescribeAutoScalingGroups in the IAM policy","Refresh/rotate AWS credentials before long operations","Stagger large rolling updates to avoid throttling","Verify with `aws autoscaling describe-auto-scaling-groups` first"],"tags":["aws","autoscaling","discovery","iam"],"backgroundTag":"aws-api-error-wrapped","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"}