hashicorp/nomad · warning
error reading attribute %s. digitalocean metadata api return
Error message
error reading attribute %s. digitalocean metadata api returned an error: resp_code: %d, resp_body: %s
What it means
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.
Source
Thrown at client/fingerprint/env_digitalocean.go:108
},
}
res, err := f.client.Do(req)
if err != nil {
f.logger.Debug("failed to request metadata", "attribute", attribute, "error", err)
return "", err
}
body, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil {
f.logger.Error("failed to read metadata", "attribute", attribute, "error", err, "resp_code", res.StatusCode)
return "", err
}
if res.StatusCode != http.StatusOK {
f.logger.Debug("could not read value for attribute", "attribute", attribute, "resp_code", res.StatusCode)
return "", fmt.Errorf("error reading attribute %s. digitalocean metadata api returned an error: resp_code: %d, resp_body: %s", attribute, res.StatusCode, body)
}
return string(body), nil
}
func (f *EnvDigitalOceanFingerprint) Fingerprint(request *FingerprintRequest, response *FingerprintResponse) error {
cfg := request.Config
// Check if we should tighten the timeout
if cfg.ReadBoolDefault(TightenNetworkTimeoutsConfig, false) {
f.client.Timeout = 1 * time.Millisecond
}
if err := f.digitalOceanProbe(); err != nil {
return wrapProbeError(err)
}
// Keys and whether they should be namespaced as unique. Any key whose valueView on GitHub (pinned to 482b49bf1a)
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
Example fix
// before: probing unsupported attribute
doGet(ctx, "tags") // 404 on old droplets
// after: check availability first
if body, err := doGet(ctx, "tags"); err == nil { ... } // or guard feature-detection Defensive patterns
Strategy: try-catch
Validate before calling
resp, err := http.Get("http://169.254.169.254/metadata/v1/hostname")
if err != nil || resp.StatusCode != http.StatusOK { /* not a DO droplet or API issue — skip fingerprint */ } Type guard
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 } Try / catch
val, err := f.Get(ctx, "hostname")
if err != nil {
var httpErr interface{ HTTPStatusCode() int }
if errors.As(err, &httpErr) && httpErr.HTTPStatusCode() == 404 { /* attribute unsupported */ }
return err
} Prevention
- Verify attribute availability on the droplet before querying
- Only enable the digitalocean fingerprint on DO hosts
- Handle 404 vs 5xx differently (unsupported vs transient)
When it happens
Trigger: Metadata endpoint returns non-200 for the requested attribute — unknown attribute path, service unavailable, or an intermediate proxy returning an error page.
Common situations: 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.
Related errors
- invalid digest format
- unsupported checksum format
- Nomad Enterprise only endpoint
- Unknown log level
- empty region value
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/f266c4b0de929675.
Report an issue: GitHub.