kubernetes/kops · error
unmarshalling IMDS response: %w
Error message
unmarshalling IMDS response: %w
What it means
queryIMDS read the IMDS response but json.Unmarshal failed to decode it into the target struct (InstanceMetadata or attestedDocument), wrapped as "unmarshalling IMDS response". The library throws this because it strictly expects the documented IMDS JSON schema; any deviation means the data cannot be trusted for identity.
Source
Thrown at upup/pkg/fi/cloudup/azure/azuremetadata/imds.go:95
resp, err := imdsHTTPClient.Do(req)
if err != nil {
return fmt.Errorf("querying IMDS %s: %w", path, err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("querying IMDS %s: status %d", path, resp.StatusCode)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("reading IMDS response: %w", err)
}
klog.V(4).Infof("Azure IMDS response: %d bytes", len(body))
if err := json.Unmarshal(body, result); err != nil {
return fmt.Errorf("unmarshalling IMDS response: %w", err)
}
return nil
}
// QueryComputeInstanceMetadata queries Azure IMDS for compute instance metadata.
// https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service#instance-metadata
func QueryComputeInstanceMetadata(ctx context.Context) (*InstanceMetadata, error) {
metadata := &InstanceMetadata{}
params := url.Values{"format": {"json"}}
if err := queryIMDS(ctx, "/metadata/instance/compute", params, metadata); err != nil {
return nil, err
}
return metadata, nil
}
// queryIMDSAttestedDocument queries the Azure IMDS attested document endpoint. The nonce is
// included in the PKCS7 signed content for replay protection.View on GitHub (pinned to 4c8573c808)
Solutions
- Dump the raw response with curl to see what's actually returned at 169.254.169.254
- Eliminate interceptors: check routes/iptables/dns for hijacked link-local traffic
- Confirm api-version compatibility; upgrade kOps if the IMDS schema changed
- Redeploy/rerun the VM if IMDS is degraded
Defensive patterns
Strategy: validation
Validate before calling
// Validate the expected IMDS JSON shape before trusting it
var probe struct {
SubscriptionID string `json:"subscriptionId"`
ResourceID string `json:"resourceId"`
}
body, _ := io.ReadAll(resp.Body)
if err := json.Unmarshal(body, &probe); err != nil {
return fmt.Errorf("IMDS returned non-JSON payload (%d bytes): %q", len(body), truncate(body))
} Try / catch
// Fail fast and dump a redacted snippet of the offending payload for diagnosis
if err != nil {
return fmt.Errorf("imds schema mismatch, aborting bootstrap: %w", err)
} Prevention
- Check for and remove any software answering on 169.254.169.254 (VPN/dns/route hijacks)
- Compare raw IMDS output against the documented schema after each api-version bump
- Validate IMDS JSON as an image bring-up smoke test
When it happens
Trigger: The body returned from IMDS is not the expected JSON: HTML error pages, empty body, a proxy/captive-portal response, or an IMDS schema change for the pinned api-version 2025-04-07.
Common situations: A device answering on 169.254.169.254 with non-JSON content (VPN software, dnsmasq, custom route); Azure changing response shape; empty 200 responses from a degraded IMDS.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- empty subscription ID
- querying instance metadata: %w
- missing resource ID
- querying attested document: %w
- empty attested document signature
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/3fd131911f144920.
Report an issue: GitHub.