{"record":{"id":"a283552d8c9f83f2","repo":"kubernetes/kops","slug":"digitalocean-access-token-is-required","errorCode":null,"errorMessage":"DIGITALOCEAN_ACCESS_TOKEN is required","messagePattern":"DIGITALOCEAN_ACCESS_TOKEN is required","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"dnsprovider/pkg/dnsprovider/providers/do/dns.go","lineNumber":70,"sourceCode":"}\n\n// TokenSource implements oauth2.TokenSource\ntype TokenSource struct {\n\tAccessToken string\n}\n\n// Token returns oauth2.Token\nfunc (t *TokenSource) Token() (*oauth2.Token, error) {\n\ttoken := &oauth2.Token{\n\t\tAccessToken: t.AccessToken,\n\t}\n\treturn token, nil\n}\n\nfunc newClient() (*godo.Client, error) {\n\taccessToken := os.Getenv(\"DIGITALOCEAN_ACCESS_TOKEN\")\n\tif accessToken == \"\" {\n\t\treturn nil, errors.New(\"DIGITALOCEAN_ACCESS_TOKEN is required\")\n\t}\n\n\ttokenSource := &TokenSource{\n\t\tAccessToken: accessToken,\n\t}\n\n\toauthClient := oauth2.NewClient(context.TODO(), tokenSource)\n\treturn godo.NewClient(oauthClient), nil\n}\n\n// DNS implements dnsprovider.Interface\ntype Interface struct {\n\tclient *godo.Client\n}\n\n// NewProvider returns an implementation of dnsprovider.Interface\nfunc NewProvider(client *godo.Client) dnsprovider.Interface {\n\treturn &Interface{client: client}","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/dnsprovider/pkg/dnsprovider/providers/do/dns.go#L52-L88","documentation":"Wraps a failure from AWSCloud.DetachInstance. Before detaching an EC2 instance from its Auto Scaling Group, kOps tags the instance with the ASG name (tagNameDetachedInstance) so the detached instance remains identifiable. If the AWS CreateTags call fails, the underlying SDK error is wrapped in this message.","triggerScenarios":"Calling DetachInstance (rolling-update / instance deletion) where CreateTags fails: instance ID does not exist or was terminated concurrently, invalid instance ID format, credentials lacking ec2:CreateTags, throttling, or a region/network failure.","commonSituations":"Instance terminated between listing and detaching during a rolling update; IAM policy missing ec2:CreateTags; stale cloud instance state in the kops model; AWS API throttling during large cluster upgrades.","solutions":["Verify the instance ID still exists with ec2.DescribeInstances before detaching","Check IAM policy grants ec2:CreateTags on the instance resource","Re-run the operation; transient throttling/network errors resolve on retry","Reconcile kops state with `kops rolling-update cluster` to refresh instance info"],"exampleFix":"// before\nif err := c.CreateTags(id, map[string]string{tagNameDetachedInstance: *asg.AutoScalingGroupName}); err != nil {\n\treturn fmt.Errorf(\"error tagging instance %q: %v\", id, err)\n}\n// after\nif _, err := c.EC2().DescribeInstances(&ec2.DescribeInstancesInput{InstanceIds: []string{id}}); err != nil {\n\treturn fmt.Errorf(\"instance %q no longer exists, skipping detach: %v\", id, err)\n}\nif err := c.CreateTags(id, map[string]string{tagNameDetachedInstance: *asg.AutoScalingGroupName}); err != nil {\n\treturn fmt.Errorf(\"error tagging instance %q: %v\", id, err)\n}","handlingStrategy":"retry","validationCode":"_, err := cloud.EC2().DescribeInstances(&ec2.DescribeInstancesInput{InstanceIds: []string{id}})\nif err != nil { return fmt.Errorf(\"instance %q not taggable: %w\", id, err) }","typeGuard":"func instanceExists(out *ec2.DescribeInstancesOutput, id string) bool {\n\tfor _, r := range out.Reservations { for _, i := range r.Instances { if aws.ToString(i.InstanceId) == id && i.State != nil && i.State.Name != ec2.InstanceStateNameTerminated { return true } } }\n\treturn false\n}","tryCatchPattern":"err := cloud.DetachInstance(ctx, instance)\nvar throttled *types.ThrottlingException\nif errors.As(err, &throttled) { backoffAndRetry(err) } else if strings.Contains(err.Error(), \"error tagging instance\") { logInvalidInstance(err) }","preventionTips":["Ensure the kOps IAM role includes ec2:CreateTags","Confirm the node still exists before issuing rolling-update cloudonly","Watch for double rolling updates on the same cluster","Handle AWS throttling with exponential backoff"],"tags":["aws","ec2","autoscaling","tagging"],"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"}