mongodb/node-mongodb-native · error · MongoCryptInvalidArgumentError

Can only provide a custom AWS credential provider when the…

Error message

Can only provide a custom AWS credential provider when the state machine is configured for automatic AWS credential fetching

What it means

Thrown by the AutoEncrypter constructor when credentialProviders.aws is defined (a custom AWS credential provider) but kmsProviders.aws contains non-empty static credentials. The driver requires that when using automatic AWS credential fetching via credentialProviders, the kmsProviders.aws entry must be an empty object ({}) to signal that credentials should be obtained dynamically. This is a MongoCryptInvalidArgumentError.

Solutions

  1. Set kmsProviders.aws to an empty object {} when using credentialProviders.aws for automatic credential fetching
  2. Remove the credentialProviders.aws callback if you want to keep using static credentials in kmsProviders.aws

Example fix

// before
new MongoClient(uri, {
  autoEncryption: {
    kmsProviders: {
      aws: { accessKeyId: 'AKIA...', secretAccessKey: '...' }
    },
    credentialProviders: { aws: myAwsProvider }
  }
});

// after (use dynamic fetching)
new MongoClient(uri, {
  autoEncryption: {
    kmsProviders: { aws: {} },
    credentialProviders: { aws: myAwsProvider }
  }
});
Defensive patterns

Strategy: validation

Validate before calling

// Before creating the MongoClient
const { kmsProviders, credentialProviders } = autoEncryptionConfig;
if (credentialProviders?.aws && kmsProviders?.aws && Object.keys(kmsProviders.aws).length > 0) {
  throw new Error('Set kmsProviders.aws to {} when using credentialProviders.aws');
}

Prevention

When it happens

Trigger: Configuring autoEncryption with both kmsProviders: { aws: { accessKeyId: '...', secretAccessKey: '...' } } and credentialProviders: { aws: async () => {...} }. The conflict is that static credentials are already provided, making the dynamic provider unnecessary and ambiguous.

Common situations: Migrating from static AWS credentials to dynamic credential fetching without removing the old kmsProviders.aws credentials; merging config from environment variables (which set static keys) with code that adds a credential provider; misunderstanding that kmsProviders.aws must be {} when using credentialProviders.aws.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11). Data as JSON: /api/errors/edab17b85107ebfb. Report an issue: GitHub.

Appendix: source

Thrown at src/client-side-encryption/auto_encrypter.ts:264

    this._client = client;
    this._bypassEncryption = options.bypassAutoEncryption === true;

    this._keyVaultNamespace = options.keyVaultNamespace || 'admin.datakeys';
    this._keyVaultClient = options.keyVaultClient || client;
    this._metaDataClient = options.metadataClient || client;
    this._proxyOptions = options.proxyOptions || {};
    if (this._proxyOptions.proxyHost && options.kmsConnectCallback) {
      throw new MongoCryptInvalidArgumentError(
        'Cannot set both proxyOptions and kmsConnectCallback'
      );
    }
    this._tlsOptions = options.tlsOptions || {};
    this._kmsConnectCallback = options.kmsConnectCallback;
    this._kmsProviders = options.kmsProviders || {};
    this._credentialProviders = options.credentialProviders;

    if (options.credentialProviders?.aws && !isEmptyCredentials('aws', this._kmsProviders)) {
      throw new MongoCryptInvalidArgumentError(
        'Can only provide a custom AWS credential provider when the state machine is configured for automatic AWS credential fetching'
      );
    }

    const mongoCryptOptions: MongoCryptOptions = {
      errorWrapper: defaultErrorWrapper
    };
    if (options.schemaMap) {
      if (ByteUtils.isUint8Array(options.schemaMap)) {
        mongoCryptOptions.schemaMap = options.schemaMap;
      } else {
        mongoCryptOptions.schemaMap = serialize(options.schemaMap);
      }
    }

    if (options.encryptedFieldsMap) {
      if (ByteUtils.isUint8Array(options.encryptedFieldsMap)) {
        mongoCryptOptions.encryptedFieldsMap = options.encryptedFieldsMap;

View on GitHub (pinned to dce7939f86)