{"record":{"id":"f39d9cec1f586eda","repo":"kubernetes/kops","slug":"failed-to-get-info-for-akamai-linode-instance-q-f39d9c","errorCode":null,"errorMessage":"failed to get info for Akamai (Linode) instance %q: empty response","messagePattern":"failed to get info for Akamai \\(Linode\\) instance %q: empty response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/linode/verifier.go","lineNumber":80,"sourceCode":"\n// VerifyToken verifies that the given token corresponds to a valid Akamai (Linode) instance.\nfunc (v *linodeVerifier) VerifyToken(ctx context.Context, rawRequest *http.Request, token string, body []byte) (*bootstrap.VerifyResult, error) {\n\tif !strings.HasPrefix(token, linodemetadata.LinodeAuthenticationTokenPrefix) {\n\t\treturn nil, bootstrap.ErrNotThisVerifier\n\t}\n\n\tinstanceIDString := strings.TrimPrefix(token, linodemetadata.LinodeAuthenticationTokenPrefix)\n\tinstanceID, err := strconv.Atoi(instanceIDString)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid authorization token\")\n\t}\n\n\tinstance, err := v.client.GetInstance(ctx, instanceID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get info for Akamai (Linode) instance %q: %w\", instanceIDString, err)\n\t}\n\tif instance == nil {\n\t\treturn nil, fmt.Errorf(\"failed to get info for Akamai (Linode) instance %q: empty response\", instanceIDString)\n\t}\n\n\taddresses, challengeEndpoints := gatherIPv4Addresses(instance.IPv4)\n\tif len(challengeEndpoints) == 0 {\n\t\treturn nil, fmt.Errorf(\"cannot determine challenge endpoint for instance id: %s\", instanceIDString)\n\t}\n\n\tresult := &bootstrap.VerifyResult{\n\t\tNodeName:          instance.Label,\n\t\tInstanceGroupName: instanceGroupNameFromTags(instance.Tags),\n\t\tCertificateNames:  addresses,\n\t\tChallengeEndpoint: challengeEndpoints[0],\n\t}\n\n\treturn result, nil\n}\n\n// gatherIPv4Addresses returns a list of IPv4 addresses and challenge endpoints from the given list of IPs.","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/linode/verifier.go#L62-L98","documentation":"VerifyToken also guards against GetInstance succeeding while returning a nil instance pointer. The linodego SDK can theoretically return (nil, nil); treating that as valid data would nil-dereference later, so the verifier returns an explicit 'empty response' error naming the instance ID. This is a defensive nil-check rather than an API-reported failure.","triggerScenarios":"v.client.GetInstance returns err == nil and instance == nil — an SDK/edge-condition response (e.g. mocked client in tests, or unexpected SDK behavior on a deleted-but-cached instance).","commonSituations":"Custom or fake linodego client implementations in tests returning (nil, nil); SDK versions with inconsistent nil handling; rarely in production because the real API returns an error rather than a nil body for missing instances.","solutions":["Inspect the SDK version's GetInstance contract; upgrade linodego if nil-nil returns are a known bug","In tests using fake clients, always return a populated *linodego.Instance or a real error","Log the instance ID and retry the lookup once before failing the verification"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"inst, err := client.GetInstance(ctx, id)\nif err != nil || inst == nil { return errors.New(\"instance lookup returned no data\") }","typeGuard":"func instanceFound(inst *linodego.Instance) bool { return inst != nil }","tryCatchPattern":"inst, err := client.GetInstance(ctx, id)\nif err != nil { return err }\nif inst == nil { return fmt.Errorf(\"instance %d: empty response\", id) }","preventionTips":["Always nil-check results even when err == nil","In test fakes, return a populated Instance or a real error, never (nil, nil)","Keep linodego updated to versions with consistent nil handling"],"tags":["linode","nil-check","sdk","defensive"],"backgroundTag":"nil-response-guard","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"}