mongodb/node-mongodb-native · error · MongoCryptAzureKMSRequestError
Malformed JSON body in GET request.
Error message
Malformed JSON body in GET request.
What it means
Thrown by the CSFLE Azure KMS credential provider when the HTTP response body from the Azure Instance Metadata Service (IMDS) endpoint (169.254.169.254) cannot be parsed as JSON. The driver calls this endpoint to fetch an access token for Azure Key Vault when automatic KMS credentials are used. A non-JSON body indicates the endpoint returned HTML (e.g. a proxy error page), an empty body, or otherwise corrupt content.
Source
Thrown at src/client-side-encryption/providers/azure.ts:75
return fetchAzureKMSToken();
}
}
/** @internal */
export const tokenCache = new AzureCredentialCache();
/** @internal */
async function parseResponse(response: {
body: string;
status?: number;
}): Promise<AzureTokenCacheEntry> {
const { status, body: rawBody } = response;
const body: { expires_in?: number; access_token?: string } = (() => {
try {
return JSON.parse(rawBody);
} catch {
throw new MongoCryptAzureKMSRequestError('Malformed JSON body in GET request.');
}
})();
if (status !== 200) {
throw new MongoCryptAzureKMSRequestError('Unable to complete request.', body);
}
if (!body.access_token) {
throw new MongoCryptAzureKMSRequestError(
'Malformed response body - missing field `access_token`.'
);
}
if (!body.expires_in) {
throw new MongoCryptAzureKMSRequestError(
'Malformed response body - missing field `expires_in`.'
);
}View on GitHub (pinned to 3366c21a63)
Solutions
- If not running on an Azure VM, supply explicit Azure KMS credentials in the KMS providers map instead of relying on IMDS auto-detection.
- Verify the host can reach 169.254.169.254: curl -H 'Metadata: true' 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://vault.azure.net'
- Disable or bypass any HTTP proxy for the link-local IP 169.254.169.254.
- Check that a system-assigned or user-assigned managed identity is enabled on the Azure VM.
Example fix
// before
const client = new MongoClient(uri, {
autoEncryption: { keyVaultNamespace: 'encryption.__dataKeys', kmsProviders: {} }
});
// after (explicit credentials when not on Azure VM)
const kmsProviders = { azure: { tenantId, clientId, clientSecret } };
const client = new MongoClient(uri, {
autoEncryption: { keyVaultNamespace: 'encryption.__dataKeys', kmsProviders }
}); Defensive patterns
Strategy: try-catch
Validate before calling
// Before constructing the AutoEncryption client, decide whether IMDS is reachable.
async function canReachAzureIMDS(): Promise<boolean> {
try {
const controller = new AbortController();
const t = setTimeout(() => controller.abort(), 2000);
const res = await fetch(
'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://vault.azure.net',
{ headers: { Metadata: 'true' }, signal: controller.signal }
);
clearTimeout(t);
if (!res.ok) return false;
await res.json(); // throws if not JSON
return true;
} catch {
return false;
}
}
const kmsProviders = (await canReachAzureIMDS()) ? {} : { azure: { tenantId, clientId, clientSecret } }; Type guard
import { MongoCryptAzureKMSRequestError } from 'mongodb';
function isAzureKMSError(e: unknown): e is MongoCryptAzureKMSRequestError {
return e instanceof MongoCryptAzureKMSRequestError;
} Try / catch
try {
const client = new MongoClient(uri, { autoEncryption: { kmsProviders, keyVaultNamespace } });
await client.connect();
} catch (err) {
if (err instanceof MongoCryptAzureKMSRequestError && /Malformed JSON/.test(err.message)) {
// IMDS not reachable; supply explicit azure credentials and retry.
}
throw err;
} Prevention
- In local/dev environments, always supply explicit azure KMS credentials rather than relying on IMDS.
- Block-test the IMDS endpoint during deployment smoke checks.
- Document the link-local IP allow-list requirement for any network namespace.
When it happens
Trigger: Triggered inside parseResponse() when JSON.parse(rawBody) throws, which is called from fetchAzureKMSToken() during CSFLE/AutoEncryption startup or token refresh when no explicit azure KMS provider credentials were supplied.
Common situations: Running CSFLE on a machine that is NOT an Azure VM (so 169.254.169.254 returns nothing or a captive-portal HTML page); corporate HTTP proxy intercepting the link-local address and returning HTML; network policy blocking the IMDS endpoint and returning an error page; attempting local development of CSFLE without providing explicit azure credentials.
Related errors
- [Azure KMS] ${error.message}
- Unable to complete request.
- Malformed response body - missing field `access_token`.
- Malformed response body - missing field `expires_in`.
- Malformed response body - unable to parse int from `expires_
AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04).
Data as JSON: /data/errors/4e1c01c0aedf063b.json.
Report an issue: GitHub.