{"record":{"id":"f700680415c44783","repo":"kubernetes/kops","slug":"zone-is-required","errorCode":null,"errorMessage":"zone is required","messagePattern":"zone is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/gce/tpm/gcetpmverifier/tpmverifier.go","lineNumber":118,"sourceCode":"\t\treturn nil, fmt.Errorf(\"incorrect Audience\")\n\t}\n\ttimeSkew := math.Abs(time.Since(time.Unix(tokenData.Timestamp, 0)).Seconds())\n\tif timeSkew > float64(v.opt.MaxTimeSkew) {\n\t\treturn nil, fmt.Errorf(\"incorrect Timestamp %v\", tokenData.Timestamp)\n\t}\n\n\t// Verify the token has signed the body content.\n\trequestHash := sha256.Sum256(body)\n\tif !bytes.Equal(requestHash[:], tokenData.RequestHash) {\n\t\treturn nil, fmt.Errorf(\"incorrect RequestHash\")\n\t}\n\n\t// Some basic validation to avoid requesting invalid instances.\n\tif tokenData.GCPProjectID == \"\" {\n\t\treturn nil, fmt.Errorf(\"gcpProjectID is required\")\n\t}\n\tif tokenData.Zone == \"\" {\n\t\treturn nil, fmt.Errorf(\"zone is required\")\n\t}\n\tif tokenData.Instance == \"\" {\n\t\treturn nil, fmt.Errorf(\"instance is required\")\n\t}\n\n\t// Verify node is in our cluster\n\tif tokenData.GCPProjectID != v.opt.ProjectID {\n\t\treturn nil, fmt.Errorf(\"projectID does not match expected: got %q, want %q\", tokenData.GCPProjectID, v.opt.ProjectID)\n\t}\n\n\tinstance, err := v.computeClient.Instances.Get(tokenData.GCPProjectID, tokenData.Zone, tokenData.Instance).Context(ctx).Do()\n\tif err != nil {\n\t\tif isNotFound(err) {\n\t\t\treturn nil, fmt.Errorf(\"unable to find instance in compute API: %w\", err)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"error fetching instance from compute API: %w\", err)\n\t}\n","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/gce/tpm/gcetpmverifier/tpmverifier.go#L100-L136","documentation":"The token must specify the GCE zone of the requesting instance; the verifier needs it to fetch the instance from the Compute API and validate its region. An empty Zone in the token payload is rejected.","triggerScenarios":"VerifyToken receives a token whose tokenData.Zone field is empty.","commonSituations":"Token producer failed to read the zone from instance metadata (`instance/zone`), older client version not populating the field, or hand-crafted test tokens missing the claim.","solutions":["Populate the zone claim from GCE instance metadata when minting the token.","Ensure the client token schema matches the verifier's expected fields.","Use the full zone path or zone name consistently with what Instances.Get expects."],"exampleFix":"// before\ntokenData := gcetpm.TokenData{GCPProjectID: projectID, Instance: instance}\n// after\nzone := metadata.Zone() // e.g. us-central1-a\ntokenData := gcetpm.TokenData{GCPProjectID: projectID, Zone: zone, Instance: instance}","handlingStrategy":"validation","validationCode":"if tokenData.Zone == \"\" {\n\treturn fmt.Errorf(\"token missing zone; read it from instance/zone metadata\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Populate zone from GCE metadata at token mint time","Fail fast client-side if any required claim is empty","Pin client versions to the schema the verifier expects"],"tags":["gcp","tpm","validation","missing-field"],"backgroundTag":"missing-required-argument","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"}