{"record":{"id":"f266c4b0de929675","repo":"hashicorp/nomad","slug":"error-reading-attribute-s-digitalocean-metadata","errorCode":null,"errorMessage":"error reading attribute %s. digitalocean metadata api returned an error: resp_code: %d, resp_body: %s","messagePattern":"error reading attribute (.+?)\\. digitalocean metadata api returned an error: resp_code: (.+?), resp_body: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"client/fingerprint/env_digitalocean.go","lineNumber":108,"sourceCode":"\t\t},\n\t}\n\n\tres, err := f.client.Do(req)\n\tif err != nil {\n\t\tf.logger.Debug(\"failed to request metadata\", \"attribute\", attribute, \"error\", err)\n\t\treturn \"\", err\n\t}\n\n\tbody, err := io.ReadAll(res.Body)\n\tres.Body.Close()\n\tif err != nil {\n\t\tf.logger.Error(\"failed to read metadata\", \"attribute\", attribute, \"error\", err, \"resp_code\", res.StatusCode)\n\t\treturn \"\", err\n\t}\n\n\tif res.StatusCode != http.StatusOK {\n\t\tf.logger.Debug(\"could not read value for attribute\", \"attribute\", attribute, \"resp_code\", res.StatusCode)\n\t\treturn \"\", fmt.Errorf(\"error reading attribute %s. digitalocean metadata api returned an error: resp_code: %d, resp_body: %s\", attribute, res.StatusCode, body)\n\t}\n\n\treturn string(body), nil\n}\n\nfunc (f *EnvDigitalOceanFingerprint) Fingerprint(request *FingerprintRequest, response *FingerprintResponse) error {\n\tcfg := request.Config\n\n\t// Check if we should tighten the timeout\n\tif cfg.ReadBoolDefault(TightenNetworkTimeoutsConfig, false) {\n\t\tf.client.Timeout = 1 * time.Millisecond\n\t}\n\n\tif err := f.digitalOceanProbe(); err != nil {\n\t\treturn wrapProbeError(err)\n\t}\n\n\t// Keys and whether they should be namespaced as unique. Any key whose value","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/fingerprint/env_digitalocean.go#L90-L126","documentation":"The DigitalOcean fingerprinter's Get method calls the DO metadata API (169.254.169.254/metadata/v1/<attribute>). When the HTTP response status is anything other than 200 OK, it logs and returns this error including the status code and response body.","triggerScenarios":"Metadata endpoint returns non-200 for the requested attribute — unknown attribute path, service unavailable, or an intermediate proxy returning an error page.","commonSituations":"Running the fingerprinter outside DigitalOcean (connection refused handled earlier) or a DO API hiccup; requesting an attribute not present on older droplets; firewall blocking the metadata service.","solutions":["Verify the droplet actually supports the requested metadata attribute (curl http://169.254.169.254/metadata/v1/hostname)","Check the resp_code in the message: 404 means attribute unsupported, 5xx means DO service issue","Confirm the DO fingerprint is enabled only on DigitalOcean hosts","Check network rules allowing link-local metadata traffic"],"exampleFix":"// before: probing unsupported attribute\ndoGet(ctx, \"tags\") // 404 on old droplets\n// after: check availability first\nif body, err := doGet(ctx, \"tags\"); err == nil { ... } // or guard feature-detection","handlingStrategy":"try-catch","validationCode":"resp, err := http.Get(\"http://169.254.169.254/metadata/v1/hostname\")\nif err != nil || resp.StatusCode != http.StatusOK { /* not a DO droplet or API issue — skip fingerprint */ }","typeGuard":"func doMetadataHealthy(ctx context.Context) bool { req, _ := http.NewRequestWithContext(ctx, \"GET\", \"http://169.254.169.254/metadata/v1/hostname\", nil); resp, err := http.DefaultClient.Do(req); if err != nil { return false }; defer resp.Body.Close(); return resp.StatusCode == http.StatusOK }","tryCatchPattern":"val, err := f.Get(ctx, \"hostname\")\nif err != nil {\n    var httpErr interface{ HTTPStatusCode() int }\n    if errors.As(err, &httpErr) && httpErr.HTTPStatusCode() == 404 { /* attribute unsupported */ }\n    return err\n}","preventionTips":["Verify attribute availability on the droplet before querying","Only enable the digitalocean fingerprint on DO hosts","Handle 404 vs 5xx differently (unsupported vs transient)"],"tags":["digitalocean","metadata-api","http"],"backgroundTag":"metadata-api-http-error","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}