mongodb/node-mongodb-native · error · MongoParseError

Text record may only set any of

Error message

Text record may only set any of: ${VALID_TXT_RECORDS.join(', ')}

What it means

The only TXT record options MongoDB+SRV permits are the keys in VALID_TXT_RECORDS (authSource, replicaSet, loadBalanced). If a TXT record carries any other key, the driver rejects it to avoid silently ignored or ambiguous configuration. This enforces the cross-driver SRV specification.

Solutions

  1. Check the TXT record content: dig TXT <srvHost>.
  2. Remove any key that is not authSource, replicaSet, or loadBalanced from the TXT record.
  3. Move those options into the connection string query string (e.g. 'mongodb+srv://host/db?tls=true&appName=foo').

Example fix

// DNS TXT before: "authSource=admin&tls=true"
// DNS TXT after:   "authSource=admin"
// URI:             mongodb+srv://host/db?tls=true
Defensive patterns

Strategy: validation

Validate before calling

import { promises as dns } from 'dns';

const VALID = ['authSource', 'replicaSet', 'loadBalanced'];

async function validateTxtKeys(srvHost: string) {
  const records = await dns.resolveTxt(srvHost);
  if (records.length === 0) return;
  const params = new URLSearchParams(records[0].join(''));
  for (const key of params.keys()) {
    if (!VALID.includes(key)) {
      throw new Error(`Invalid TXT key '${key}'. Allowed: ${VALID.join(', ')}`);
    }
  }
}

Prevention

When it happens

Trigger: A mongodb+srv:// URI whose DNS TXT record contains key=value pairs outside the allowed set (e.g. 'tls=true', 'appName=foo', 'connectTimeoutMS=5000').

Common situations: An operator tries to set TLS, timeouts, or appName via DNS TXT instead of the URI query string, not realizing SRV TXT only allows three keys.

Related errors


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

Appendix: source

Thrown at src/connection_string.ts:123

  // Use the result of resolving the TXT record and add options from there if they exist.
  let record;
  try {
    record = await txtResolutionPromise;
  } catch (error) {
    if (error.code !== 'ENODATA' && error.code !== 'ENOTFOUND') {
      throw error;
    }
    return hostAddresses;
  }

  if (record.length > 1) {
    throw new MongoParseError('Multiple text records not allowed');
  }

  const txtRecordOptions = new URLSearchParams(record[0].join(''));
  const txtRecordOptionKeys = [...txtRecordOptions.keys()];
  if (txtRecordOptionKeys.some(key => !VALID_TXT_RECORDS.includes(key))) {
    throw new MongoParseError(`Text record may only set any of: ${VALID_TXT_RECORDS.join(', ')}`);
  }

  if (VALID_TXT_RECORDS.some(option => txtRecordOptions.get(option) === '')) {
    throw new MongoParseError('Cannot have empty URI params in DNS TXT Record');
  }

  const source = txtRecordOptions.get('authSource') ?? undefined;
  const replicaSet = txtRecordOptions.get('replicaSet') ?? undefined;
  const loadBalanced = txtRecordOptions.get('loadBalanced') ?? undefined;

  if (
    !options.userSpecifiedAuthSource &&
    source &&
    options.credentials &&
    !AUTH_MECHS_AUTH_SRC_EXTERNAL.has(options.credentials.mechanism)
  ) {
    options.credentials = MongoCredentials.merge(options.credentials, { source });
  }

View on GitHub (pinned to dce7939f86)