kubernetes/kops · error

cannot determine challenge endpoint for server %d

Error message

cannot determine challenge endpoint for server %d

What it means

VerifyToken builds challenge endpoints only from the server's private-network interfaces (server.PrivateNet); Hetzner intentionally does not challenge over the public network. If the server has no private network attachment (or none of the attachments carry an IP), no challenge endpoint can be determined and this error is thrown, blocking node bootstrap verification.

Source

Thrown at upup/pkg/fi/cloudup/hetzner/verifier.go:92

	if err != nil || server == nil {
		return nil, fmt.Errorf("failed to get info for server %q: %w", token, err)
	}

	var addrs []string
	var challengeEndpoints []string
	if server.PublicNet.IPv4.IP != nil {
		// Don't challenge over the public network
		addrs = append(addrs, server.PublicNet.IPv4.IP.String())
	}
	for _, network := range server.PrivateNet {
		if network.IP != nil {
			addrs = append(addrs, network.IP.String())
			challengeEndpoints = append(challengeEndpoints, net.JoinHostPort(network.IP.String(), strconv.Itoa(wellknownports.NodeupChallenge)))
		}
	}

	if len(challengeEndpoints) == 0 {
		return nil, fmt.Errorf("cannot determine challenge endpoint for server %d", serverID)
	}

	result := &bootstrap.VerifyResult{
		NodeName:          server.Name,
		CertificateNames:  addrs,
		ChallengeEndpoint: challengeEndpoints[0],
	}

	for key, value := range server.Labels {
		if key == TagKubernetesInstanceGroup {
			result.InstanceGroupName = value
		}
	}

	return result, nil
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Attach the server to the cluster's Hetzner private network (hcloud server attach-to-network or recreate via kOps) so it has a private IP.
  2. Ensure the cluster spec includes a Hetzner network so new nodes are attached at creation time, then re-run the node bootstrap.
  3. Verify the network attachment completed and the interface received an IP in the Hetzner console/API before retrying verification.
Defensive patterns

Strategy: validation

Validate before calling

srv, _, err := client.Server.GetByID(ctx, serverID)
if err != nil || srv == nil {
    return fmt.Errorf("server %d not reachable: %v", serverID, err)
}
if len(srv.PrivateNet) == 0 {
    return fmt.Errorf("server %d has no private network attachment; attach it to the cluster network before bootstrapping", serverID)
}

Type guard

func hasChallengeEndpoint(s *hcloud.Server) bool {
    for _, n := range s.PrivateNet {
        if n.IP != nil { return true }
    }
    return false
}

Prevention

When it happens

Trigger: The Hetzner server presenting the bootstrap token is not attached to any private network (hcloud_network_attachment), or the attachment exists but the interface has no assigned IP, so len(challengeEndpoints)==0.

Common situations: Cluster provisioned without a Hetzner network (networking configured with public IPs only); server removed from the network while nodeup still holds a valid token; kOps clusters upgraded to challenge-based bootstrap before the network was attached.

Related errors


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