{"record":{"id":"3f03be689bd62776","repo":"kubernetes/kops","slug":"droplet-metadata-returned-non-200-status-code-d","errorCode":null,"errorMessage":"droplet metadata returned non-200 status code: %d","messagePattern":"droplet metadata returned non-200 status code: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/nodeidentity/do/identify.go","lineNumber":107,"sourceCode":"\tif accessToken == \"\" {\n\t\treturn nil, errors.New(\"DIGITALOCEAN_ACCESS_TOKEN is required\")\n\t}\n\n\ttokenSource := &TokenSource{AccessToken: accessToken}\n\toauthClient := oauth2.NewClient(context.TODO(), tokenSource)\n\treturn godo.NewClient(oauthClient), nil\n}\n\nfunc getMetadata(url string) (string, error) {\n\tresp, err := http.Get(url)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to get metadata URL %s: %v\", url, err)\n\t}\n\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn \"\", fmt.Errorf(\"droplet metadata returned non-200 status code: %d\", resp.StatusCode)\n\t}\n\n\tbodyBytes, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to read metadata information %s: %v\", url, err)\n\t}\n\n\treturn string(bodyBytes), nil\n}\n\n// IdentifyNode queries DigitalOcean 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 == \"\" {\n\t\treturn nil, errors.New(\"provider ID cannot be empty\")\n\t}\n\n\tconst prefix = \"digitalocean://\"","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/nodeidentity/do/identify.go#L89-L125","documentation":"getMetadata fetches a URL from the DigitalOcean droplet metadata service (169.254.169.254). When the HTTP response status is not 200 OK, it aborts and wraps the status code in this error, meaning the metadata endpoint answered but could not serve the requested value.","triggerScenarios":"The metadata service returns 404 (requested metadata key not exposed), 503 (metadata service temporarily unavailable), or 403 on an internal link from within a droplet via getMetadataRegion.","commonSituations":"Running on a non-DigitalOcean host where the metadata endpoint exists but lacks the key; DigitalOcean metadata service degraded/unavailable; wrong metadata path constructed; proxy or firewall intercepting link-local requests.","solutions":["Check the exact status code in the error to identify whether it is 404 (bad path/key), 503 (retry later), or 403 (access blocked)","Confirm the workload is actually running on a DigitalOcean droplet that supports the droplet metadata service","Retry the operation; transient 5xx from the metadata service usually resolves","Verify the metadata URL path matches the current DigitalOcean metadata API (e.g. /metadata/v1/region)","Check for network interception of 169.254.169.254 (custom firewalls, link-local routing issues)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"resp, err := http.Get(metadataURL)\nif err != nil { return err }\nif resp.StatusCode != http.StatusOK {\n    return fmt.Errorf(\"metadata unavailable: status %d\", resp.StatusCode)\n}","typeGuard":null,"tryCatchPattern":"body, err := getMetadata(url)\nif err != nil {\n    var netErr net.Error\n    if errors.As(err, &netErr) || strings.Contains(err.Error(), \"non-200\") {\n        // retry with backoff or fall back to cached region\n    }\n}","preventionTips":["Only invoke DO metadata lookups on hosts that are DigitalOcean droplets","Add retry with exponential backoff for transient 5xx responses","Cache the last-known region value as a fallback","Monitor/health-check 169.254.169.254 reachability on startup"],"tags":["digitalocean","metadata","http","network"],"backgroundTag":"metadata-service-non-200","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"}