kubernetes/kops · error

unknown topology type

Error message

unknown topology type: %q

What it means

setupAPI configures how the Kubernetes API endpoint is exposed and bases decisions on opt.Topology. Its switch only knows public and private; any other topology value reaching here (after the earlier validation) is rejected with this defensive error while creating the cluster.

Solutions

  1. Set NewClusterOptions.Topology to "public" or "private" only.
  2. In Go, use the api.TopologyPublic / api.TopologyPrivate constants.
  3. Ensure the --topology flag value is validated before NewCluster is invoked.

Example fix

// before
opt := &NewClusterOptions{Topology: "public,private"}
// after
opt := &NewClusterOptions{Topology: api.TopologyPrivate}
Defensive patterns

Strategy: type-guard

Validate before calling

if opt.Topology != api.TopologyPublic && opt.Topology != api.TopologyPrivate { return fmt.Errorf("topology must be public or private") }

Type guard

func isValidTopology(t string) bool { return t == api.TopologyPublic || t == api.TopologyPrivate }

Try / catch

if err := NewCluster(ctx, cloud, opt); err != nil && strings.Contains(err.Error(), "unknown topology type") { /* fix NewClusterOptions.Topology to a constant and retry */ }

Prevention

When it happens

Trigger: NewClusterOptions.Topology set to a value other than api.TopologyPublic/api.TopologyPrivate while API access configuration requires topology-specific handling — normally only reachable when constructing options programmatically (Topology field set directly) or when earlier validation is bypassed.

Common situations: Go code/tests building NewClusterOptions with an arbitrary Topology string; scripts mutated between validation and use; refactors that removed the setupTopology validation path.

Understand the failure class

Background: "unknown output mode", "invalid value for flag", "expects true/false": fixing invalid flag value errors in CLI tools — this error's family across 24 libraries.

Related errors


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

Appendix: source

Thrown at upup/pkg/fi/cloudup/new_cluster.go:1561

	// Populate the API access, so that it can be discoverable
	klog.Infof("Cloud Provider ID: %q", cluster.GetCloudProvider())
	if opt.APILoadBalancerType != "" || opt.APISSLCertificate != "" {
		cluster.Spec.API.LoadBalancer = &api.LoadBalancerAccessSpec{}
	} else {
		switch opt.Topology {
		case api.TopologyPublic:
			if cluster.UsesNoneDNS() {
				// there are no DNS records for the API, so we use a LoadBalancer instead
				cluster.Spec.API.LoadBalancer = &api.LoadBalancerAccessSpec{}
			} else {
				cluster.Spec.API.DNS = &api.DNSAccessSpec{}
			}

		case api.TopologyPrivate:
			cluster.Spec.API.LoadBalancer = &api.LoadBalancerAccessSpec{}

		default:
			return fmt.Errorf("unknown topology type: %q", opt.Topology)
		}
	}

	if cluster.Spec.API.LoadBalancer != nil && cluster.Spec.API.LoadBalancer.Type == "" {
		switch opt.APILoadBalancerType {
		case "", "public":
			cluster.Spec.API.LoadBalancer.Type = api.LoadBalancerTypePublic
		case "internal":
			cluster.Spec.API.LoadBalancer.Type = api.LoadBalancerTypeInternal
		default:
			return fmt.Errorf("unknown api-loadbalancer-type: %q", opt.APILoadBalancerType)
		}
	}

	if cluster.Spec.API.LoadBalancer != nil && opt.APISSLCertificate != "" {
		cluster.Spec.API.LoadBalancer.SSLCertificate = opt.APISSLCertificate
	}

View on GitHub (pinned to 4c8573c808)