{"record":{"id":"c91ed486d9c25bad","repo":"kubernetes/kops","slug":"s-is-required","errorCode":null,"errorMessage":"%s is required","messagePattern":"(.+?) is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/nodeidentity/hetzner/identify.go","lineNumber":53,"sourceCode":"\t\"k8s.io/kops/upup/pkg/fi/cloudup/hetzner\"\n)\n\nconst (\n\tcacheTTL = 60 * time.Minute\n)\n\n// nodeIdentifier identifies a node from Hetzner Cloud\ntype nodeIdentifier struct {\n\tclient       *hcloud.Client\n\tcache        expirationcache.Store\n\tcacheEnabled bool\n}\n\n// New creates and returns a nodeidentity.Identifier for Nodes running on Hetzner Cloud\nfunc New(cacheNodeidentityInfo bool) (nodeidentity.Identifier, error) {\n\thcloudToken := os.Getenv(\"HCLOUD_TOKEN\")\n\tif hcloudToken == \"\" {\n\t\treturn nil, fmt.Errorf(\"%s is required\", \"HCLOUD_TOKEN\")\n\t}\n\topts := []hcloud.ClientOption{\n\t\thcloud.WithToken(hcloudToken),\n\t\thcloud.WithApplication(\"kops\", version.Version),\n\t}\n\thcloudClient := hcloud.NewClient(opts...)\n\n\treturn &nodeIdentifier{\n\t\tclient:       hcloudClient,\n\t\tcache:        expirationcache.NewTTLStore(stringKeyFunc, cacheTTL),\n\t\tcacheEnabled: cacheNodeidentityInfo,\n\t}, nil\n}\n\n// IdentifyNode queries Hetzner Cloud for the node identity information\nfunc (i *nodeIdentifier) IdentifyNode(ctx context.Context, node *corev1.Node) (*nodeidentity.Info, error) {\n\tproviderID := node.Spec.ProviderID\n\tif providerID == \"\" {","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/nodeidentity/hetzner/identify.go#L35-L71","documentation":"The Hetzner node identity provider refuses to start when the HCLOUD_TOKEN environment variable is empty, because no Hetzner Cloud API client can be constructed without an auth token. New() is the constructor for the identifier used by kops' node-authorizer/node controller.","triggerScenarios":"New(cacheNodeidentityInfo bool) runs with os.Getenv(\"HCLOUD_TOKEN\") == \"\" — i.e., the kops controller (e.g., kops-controller DaemonSet) was deployed without the HCLOUD_TOKEN env var set.","commonSituations":"kops-controller manifest edited and the env var/secret reference dropped; secret created in the wrong namespace; typo in env var name; upgrading kops-controller without re-applying the secret.","solutions":["Set HCLOUD_TOKEN in the kops-controller pod spec (from a Kubernetes Secret)","Verify the token is a valid Hetzner Cloud API token with read permission","Recreate the pod after fixing the env so the new value is picked up"],"exampleFix":"// before\n// kops-controller pod without HCLOUD_TOKEN -> crash on startup\n// after (pod env)\nenv:\n- name: HCLOUD_TOKEN\n  valueFrom:\n    secretKeyRef:\n      name: kops-controller\n      key: hcloud-token","handlingStrategy":"validation","validationCode":"if os.Getenv(\"HCLOUD_TOKEN\") == \"\" {\n  return fmt.Errorf(\"HCLOUD_TOKEN is required\")\n}","typeGuard":null,"tryCatchPattern":"id, err := nodeidentityhetzner.New(cache)\nif err != nil {\n  log.Fatalf(\"hetzner identity init: %v\", err) // fail fast at startup\n}","preventionTips":["Never edit kops-controller manifests by hand; use kops cluster spec","Validate the token Secret exists in the controller namespace before rollout","Add a startup readiness check that fails loudly on missing env"],"tags":["hetzner","configuration","missing-env-var","startup"],"backgroundTag":"missing-env-var","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}