{"record":{"id":"96eb619b28888b6d","repo":"kubernetes/kops","slug":"cannot-determine-challenge-endpoint-for-server-d-96eb61","errorCode":null,"errorMessage":"cannot determine challenge endpoint for server %d","messagePattern":"cannot determine challenge endpoint for server (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/hetzner/verifier.go","lineNumber":92,"sourceCode":"\tif err != nil || server == nil {\n\t\treturn nil, fmt.Errorf(\"failed to get info for server %q: %w\", token, err)\n\t}\n\n\tvar addrs []string\n\tvar challengeEndpoints []string\n\tif server.PublicNet.IPv4.IP != nil {\n\t\t// Don't challenge over the public network\n\t\taddrs = append(addrs, server.PublicNet.IPv4.IP.String())\n\t}\n\tfor _, network := range server.PrivateNet {\n\t\tif network.IP != nil {\n\t\t\taddrs = append(addrs, network.IP.String())\n\t\t\tchallengeEndpoints = append(challengeEndpoints, net.JoinHostPort(network.IP.String(), strconv.Itoa(wellknownports.NodeupChallenge)))\n\t\t}\n\t}\n\n\tif len(challengeEndpoints) == 0 {\n\t\treturn nil, fmt.Errorf(\"cannot determine challenge endpoint for server %d\", serverID)\n\t}\n\n\tresult := &bootstrap.VerifyResult{\n\t\tNodeName:          server.Name,\n\t\tCertificateNames:  addrs,\n\t\tChallengeEndpoint: challengeEndpoints[0],\n\t}\n\n\tfor key, value := range server.Labels {\n\t\tif key == TagKubernetesInstanceGroup {\n\t\t\tresult.InstanceGroupName = value\n\t\t}\n\t}\n\n\treturn result, nil\n}\n","sourceCodeStart":74,"sourceCodeEnd":109,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/hetzner/verifier.go#L74-L109","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Ensure the cluster spec includes a Hetzner network so new nodes are attached at creation time, then re-run the node bootstrap.","Verify the network attachment completed and the interface received an IP in the Hetzner console/API before retrying verification."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"srv, _, err := client.Server.GetByID(ctx, serverID)\nif err != nil || srv == nil {\n    return fmt.Errorf(\"server %d not reachable: %v\", serverID, err)\n}\nif len(srv.PrivateNet) == 0 {\n    return fmt.Errorf(\"server %d has no private network attachment; attach it to the cluster network before bootstrapping\", serverID)\n}","typeGuard":"func hasChallengeEndpoint(s *hcloud.Server) bool {\n    for _, n := range s.PrivateNet {\n        if n.IP != nil { return true }\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Always create kOps Hetzner clusters with a network so nodes are attached automatically","Never detach a node from its private network while nodeup tokens are pending verification","Verify the private-net IP is assigned in the Hetzner console after attaching a server"],"tags":["hetzner","networking","bootstrap"],"backgroundTag":"missing-private-network","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"}