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

  1. Dump the raw response with curl to see what's actually returned at 169.254.169.254
  2. Eliminate interceptors: check routes/iptables/dns for hijacked link-local traffic
  3. Confirm api-version compatibility; upgrade kOps if the IMDS schema changed
  4. 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

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


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/3fd131911f144920. Report an issue: GitHub.