kubernetes/kops · error

found multiple hosted zones matched name %q

Error message

found multiple hosted zones matched name %q

What it means

findExisting matched more than one Route53 hosted zone with the same DNS name and the same private/public setting, so kOps cannot determine which zone the DNSZone task refers to and aborts instead of guessing. Route53 permits duplicate zone names across accounts/within limits, so ambiguity must be resolved by the user.

Source

Thrown at upup/pkg/fi/cloudup/awstasks/dnszone.go:150

		DNSName: aws.String(findName),
	}

	response, err := cloud.Route53().ListHostedZonesByName(ctx, request)
	if err != nil {
		return nil, fmt.Errorf("error listing DNS HostedZones: %v", err)
	}

	var zones []route53types.HostedZone
	for _, zone := range response.HostedZones {
		if aws.ToString(zone.Name) == findName && zone.Config.PrivateZone == fi.ValueOf(e.Private) {
			zones = append(zones, zone)
		}
	}

	if len(zones) == 0 {
		return nil, nil
	} else if len(zones) != 1 {
		return nil, fmt.Errorf("found multiple hosted zones matched name %q", findName)
	} else {
		request := &route53.GetHostedZoneInput{
			Id: zones[0].Id,
		}

		response, err := cloud.Route53().GetHostedZone(ctx, request)
		if err != nil {
			return nil, fmt.Errorf("error fetching DNS HostedZone by id %q: %v", *request.Id, err)
		}

		return response, nil
	}
}

func (e *DNSZone) Run(c *fi.CloudupContext) error {
	return fi.CloudupDefaultDeltaRunMethod(e, c)
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Set the zone's ID explicitly in the cluster spec (spec.dnsZone / ZoneID) so findExisting uses GetHostedZone by ID and skips the ambiguous name search
  2. Delete or rename the duplicate hosted zone (`aws route53 list-hosted-zones-by-name --dns-name example.com.` then delete the unwanted one)
  3. Differentiate by making one zone private and the other public if that matches intent

Example fix

// cluster.yaml — before
cluster.spec.dnsZone: example.com
// after
cluster.spec.dnsZone: Z123456ABCDEFG  # explicit hosted zone id
Defensive patterns

Strategy: validation

Validate before calling

func assertUniqueZone(ctx context.Context, r53 *route53.Client, dnsName string, private bool) error {
    name := strings.TrimSuffix(dnsName, ".") + "."
    out, err := r53.ListHostedZonesByName(ctx, &route53.ListHostedZonesByNameInput{DNSName: aws.String(name)})
    if err != nil {
        return err
    }
    n := 0
    for _, z := range out.HostedZones {
        if aws.ToString(z.Name) == name && z.Config.PrivateZone == private {
            n++
        }
    }
    if n > 1 {
        return fmt.Errorf("%d hosted zones named %q (private=%v); set an explicit zone ID", n, name, private)
    }
    return nil
}

Type guard

func uniqueZoneID(zones []route53types.HostedZone, name string, private bool) (string, bool) {
    var ids []string
    for _, z := range zones {
        if aws.ToString(z.Name) == name && z.Config.PrivateZone == private {
            ids = append(ids, aws.ToString(z.Id))
        }
    }
    if len(ids) == 1 {
        return ids[0], true
    }
    return "", false
}

Prevention

When it happens

Trigger: Two or more hosted zones in the account share the exact DNSName (with trailing dot) of e.DNSName and the same PrivateZone value as e.Private, while the task spec carries no ZoneID.

Common situations: A previous failed kOps run created a zone, then the zone was recreated manually or by another run; importing the same cluster twice into one account; leftover zones from destroyed clusters that kept the domain.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/ea74c31edbfcc0ef. Report an issue: GitHub.