mongodb/node-mongodb-native · error · MongoAPIError

Server record does not have at least one more domain level…

Error message

Server record does not have at least one more domain level than parent URI

What it means

Thrown by checkParentDomainMatch() when the SRV hostname has fewer than three dot-separated parts and a returned SRV record address does not contain at least one more domain level than the parent srvHost. This is a security guard: SRV records for short hosts (e.g. 'cluster.mongodb.net') must advertise addresses with strictly deeper domains to prevent DNS hijacking via sibling/subdomain tricks. Raised as MongoAPIError.

Solutions

  1. Ensure SRV records advertise addresses that are subdomains of (deeper than) the srvHost.
  2. Use a fully-qualified srvHost with at least three domain parts (e.g. cluster.example.com).
  3. Verify DNS configuration with 'dig SRV _mongodb._tcp.your.srv.host' and fix malformed records.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await client.connect();
} catch (e) {
  if (e instanceof MongoAPIError && /at least one more domain level/.test(e.message)) {
    // fix SRV records to advertise deeper subdomains; use a >=3-part srvHost
  } else throw e;
}

Prevention

When it happens

Trigger: Connecting via a mongodb+srv:// connection string where the DNS SRV response advertises an address whose domain depth is not greater than the srvHost when the srvHost has fewer than three parts. Typically a DNS misconfiguration or, in worst case, a compromised DNS server.

Common situations: Custom or private DNS deployments with short srvHost names (fewer than three labels). Misconfigured SRV records in internal service discovery. Rare on standard Atlas-style hostnames which have >= 3 parts.

Related errors


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

Appendix: source

Thrown at src/utils.ts:1181

  const allCharacterBeforeFirstDot = /^.*?\./;
  const srvIsLessThanThreeParts = normalizedSrvHost.split('.').length < 3;
  // Remove all characters before first dot
  // Add leading dot back to string so
  //   an srvHostDomain = '.trusted.site'
  //   will not satisfy an addressDomain that endsWith '.fake-trusted.site'
  const addressDomain = `.${normalizedAddress.replace(allCharacterBeforeFirstDot, '')}`;
  let srvHostDomain = srvIsLessThanThreeParts
    ? normalizedSrvHost
    : `.${normalizedSrvHost.replace(allCharacterBeforeFirstDot, '')}`;

  if (!srvHostDomain.startsWith('.')) {
    srvHostDomain = '.' + srvHostDomain;
  }
  if (
    srvIsLessThanThreeParts &&
    normalizedAddress.split('.').length <= normalizedSrvHost.split('.').length
  ) {
    throw new MongoAPIError(
      'Server record does not have at least one more domain level than parent URI'
    );
  }
  if (!addressDomain.endsWith(srvHostDomain)) {
    throw new MongoAPIError('Server record does not share hostname with parent URI');
  }
}

/**
 * Perform a get request that returns status and body.
 * @internal
 */
export function get(
  url: URL | string,
  options: http.RequestOptions = {}
): Promise<{ body: string; status: number | undefined }> {
  return new Promise((resolve, reject) => {
    /* eslint-disable prefer-const */

View on GitHub (pinned to dce7939f86)