{"record":{"id":"39d37f12f0ec8ecf","repo":"kubernetes/kops","slug":"error-creating-resourcerecordsets-v","errorCode":null,"errorMessage":"error creating ResourceRecordSets: %v","messagePattern":"error creating ResourceRecordSets: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/awstasks/dnsname.go","lineNumber":215,"sourceCode":"\t}\n\n\tchange := route53types.Change{\n\t\tAction:            route53types.ChangeActionUpsert,\n\t\tResourceRecordSet: rrs,\n\t}\n\n\tchangeBatch := &route53types.ChangeBatch{}\n\tchangeBatch.Changes = []route53types.Change{change}\n\n\trequest := &route53.ChangeResourceRecordSetsInput{}\n\trequest.HostedZoneId = e.Zone.ZoneID\n\trequest.ChangeBatch = changeBatch\n\n\tklog.V(2).Infof(\"Updating DNS record %q\", *e.ResourceName)\n\n\tresponse, err := t.Cloud.Route53().ChangeResourceRecordSets(context.TODO(), request)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error creating ResourceRecordSets: %v\", err)\n\t}\n\n\tklog.V(2).Infof(\"Change id is %q\", aws.ToString(response.ChangeInfo.Id))\n\n\treturn nil\n}\n\ntype terraformRoute53Record struct {\n\tName    *string  `cty:\"name\"`\n\tType    *string  `cty:\"type\"`\n\tTTL     *string  `cty:\"ttl\"`\n\tRecords []string `cty:\"records\"`\n\n\tAlias  *terraformAlias          `cty:\"alias\"`\n\tZoneID *terraformWriter.Literal `cty:\"zone_id\"`\n}\n\ntype terraformAlias struct {","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/awstasks/dnsname.go#L197-L233","documentation":"In DNSName.RenderAWS, kops issues a Route53 ChangeResourceRecordSets UPSERT for the record; any API rejection is wrapped as 'error creating ResourceRecordSets' (dnsname.go:215). The Route53 error (InvalidChangeBatch, NoSuchHostedZone, AccessDenied, concurrent change) is appended via %v.","triggerScenarios":"ChangeResourceRecordSets fails: invalid ResourceName/Type combination in the ChangeBatch, HostedZoneId (e.Zone.ZoneID) wrong or deleted, IAM lacks route53:ChangeResourceRecordSets, malformed alias target (bad hosted zone ID for the NLB), or a conflicting concurrent change.","commonSituations":"Zone deleted between Find and Apply; record name with invalid characters or trailing-dot mismatch; read-only IAM policy on Route53; alias target referencing an NLB in an incompatible zone; concurrent kops runs colliding on the same record.","solutions":["Read the wrapped Route53 error (InvalidChangeBatch, NoSuchHostedZone, AccessDenied) and fix that specific cause","If NoSuchHostedZone: recreate/verify the hosted zone and update the cluster spec","If AccessDenied: grant route53:ChangeResourceRecordSets to the kops credentials","If InvalidChangeBatch: verify ResourceName is well-formed and ResourceType (A/AAAA/CNAME) is valid for the alias","Avoid concurrent kops update runs against the same zone"],"exampleFix":"// before: read-only Route53 policy\n{\"Action\": [\"route53:List*\", \"route53:Get*\"], \"Effect\": \"Allow\"}\n// after\n{\"Action\": [\"route53:List*\", \"route53:Get*\", \"route53:ChangeResourceRecordSets\"], \"Effect\": \"Allow\", \"Resource\": \"*\"}","handlingStrategy":"retry","validationCode":"// Validate zone + record ownership before issuing the change\nzone, err := r53.GetHostedZone(ctx, &route53.GetHostedZoneInput{Id: e.Zone.ZoneID})\nif err != nil {\n\treturn fmt.Errorf(\"zone %s unavailable: %w\", aws.ToString(e.Zone.ZoneID), err)\n}\nzoneName := strings.TrimSuffix(aws.ToString(zone.HostedZone.Name), \".\")\nif !strings.HasSuffix(strings.TrimSuffix(aws.ToString(e.ResourceName), \".\"), zoneName) {\n\treturn fmt.Errorf(\"record %s does not belong to zone %s\", aws.ToString(e.ResourceName), zoneName)\n}","typeGuard":null,"tryCatchPattern":"_, err := r53.ChangeResourceRecordSets(ctx, req)\nif err != nil {\n\tvar batch *route53types.InvalidChangeBatch\n\tif errors.As(err, &batch) {\n\t\t// fix record name/type in the spec — do not retry\n\t}\n\tvar th *route53types.ThrottlingException\n\tif errors.As(err, &th) {\n\t\t// exponential backoff and retry\n\t}\n\treturn err\n}","preventionTips":["Do not run concurrent kops update runs against the same hosted zone","Confirm the hosted zone still exists right before applying (zones can be deleted out-of-band)","Grant route53:ChangeResourceRecordSets, not just read permissions","Use only alias-valid resource types (A/AAAA/CNAME) and well-formed record names","Inspect InvalidChangeBatch details in the wrapped error before retrying"],"tags":["aws","route53","dns","kops","resource-record-set"],"backgroundTag":"aws-api-permission-denied","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"}