{"record":{"id":"ac9932e13df61e6b","repo":"kubernetes/kops","slug":"error-describing-instance-health-v","errorCode":null,"errorMessage":"error describing instance health: %v","messagePattern":"error describing instance health: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/awsup/aws_cloud.go","lineNumber":568,"sourceCode":"\n\treturn nil\n}\n\n// deregisterInstanceFromClassicLoadBalancer ensures that connectionDraining completes for the associated classic loadBalancer to ensure no dropped connections.\nfunc deregisterInstanceFromClassicLoadBalancer(ctx context.Context, c AWSCloud, loadBalancerNames []string, instanceId string) error {\n\tklog.Infof(\"Deregistering instance from classic loadBalancers: %v\", loadBalancerNames)\n\n\tfor {\n\t\tinstanceDraining := false\n\t\tfor _, loadBalancerName := range loadBalancerNames {\n\t\t\tresponse, err := c.ELB().DescribeInstanceHealth(ctx, &elb.DescribeInstanceHealthInput{\n\t\t\t\tLoadBalancerName: aws.String(loadBalancerName),\n\t\t\t\tInstances: []elbtypes.Instance{{\n\t\t\t\t\tInstanceId: aws.String(instanceId),\n\t\t\t\t}},\n\t\t\t})\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error describing instance health: %v\", err)\n\t\t\t}\n\n\t\t\t// describeInstanceHealth can return an empty list if the instance was already terminated.\n\t\t\tif len(response.InstanceStates) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// there will be only one instance in the DescribeInstanceHealth response.\n\t\t\tif aws.ToString(response.InstanceStates[0].State) == instanceInServiceState {\n\t\t\t\tc.ELB().DeregisterInstancesFromLoadBalancer(ctx, &elb.DeregisterInstancesFromLoadBalancerInput{\n\t\t\t\t\tLoadBalancerName: aws.String(loadBalancerName),\n\t\t\t\t\tInstances: []elbtypes.Instance{{\n\t\t\t\t\t\tInstanceId: aws.String(instanceId),\n\t\t\t\t\t}},\n\t\t\t\t})\n\t\t\t\tinstanceDraining = true\n\t\t\t}\n\t\t}","sourceCodeStart":550,"sourceCodeEnd":586,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/awsup/aws_cloud.go#L550-L586","documentation":"deregisterInstanceFromClassicLoadBalancer polls DescribeInstanceHealth in a loop to check the instance's state on each Classic ELB; an AWS SDK error from that call aborts the drain with this wrapped error. kOps cannot confirm whether the instance is InService, so it will not deregister/terminate and risk dropping connections.","triggerScenarios":"c.ELB().DescribeInstanceHealth returns an error — typically AccessDenied (missing elb:DescribeInstanceHealth), LoadBalancerNotFound (ELB deleted while ASG still references it), throttling, or a network failure during the polling loop.","commonSituations":"Classic ELB deleted out-of-band but still attached to the ASG's LoadBalancerNames; IAM policy gaps; regional misconfiguration; ELB API throttling during big rolling updates.","solutions":["Check whether the named Classic ELB still exists; if deleted, remove it from the ASG's LoadBalancerNames (or update the cluster spec) and retry","Ensure IAM grants elb:DescribeInstanceHealth","Retry on transient throttling/network errors","Migrate off Classic ELBs to NLB/ALB target groups if the legacy ELB stack keeps causing drift"],"exampleFix":"// before\n// error describing instance health: AccessDenied: not authorized to perform: elasticloadbalancing:DescribeInstanceHealth\n// after: IAM statement\n{\"Effect\":\"Allow\",\"Action\":[\"elasticloadbalancing:DescribeInstanceHealth\"],\"Resource\":\"*\"}","handlingStrategy":"retry","validationCode":"_, err := elbSvc.DescribeLoadBalancers(&elb.DescribeLoadBalancersInput{LoadBalancerNames: lbNames})\nif err != nil {\n\treturn fmt.Errorf(\"referenced classic ELB missing/unreachable: %w\", err)\n}","typeGuard":"func isELBNotFound(err error) bool {\n\tvar ae smithy.APIError\n\treturn errors.As(err, &ae) && ae.ErrorCode() == \"LoadBalancerNotFound\"\n}","tryCatchPattern":"if err := cloud.DeregisterInstance(inst); err != nil {\n\tif strings.Contains(err.Error(), \"error describing instance health\") {\n\t\tvar ae smithy.APIError\n\t\tif errors.As(err, &ae) && ae.ErrorCode() == \"LoadBalancerNotFound\" {\n\t\t\treturn detachStaleELBFromASG(asgName) // remove stale ref, then retry\n\t\t}\n\t\treturn retryWithBackoff(3, 5*time.Second, func() error { return cloud.DeregisterInstance(inst) })\n\t}\n\treturn err\n}","preventionTips":["Grant elb:DescribeInstanceHealth in IAM","Remove deleted Classic ELBs from ASG LoadBalancerNames promptly","Prefer ALB/NLB target groups over Classic ELBs","Back off on throttling instead of tight-polling"],"tags":["aws","elb","classic-load-balancer","health-check"],"backgroundTag":"elb-describe-instance-health-failed","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"}