mongodb/node-mongodb-native · error · MongoOIDCError

OIDC callback timed out after ${HUMAN_TIMEOUT_MS}ms.

Error message

OIDC callback timed out after ${HUMAN_TIMEOUT_MS}ms.

What it means

Thrown by the human OIDC callback workflow when the OIDC callback does not return within HUMAN_TIMEOUT_MS (300000ms / 5 minutes) - see src/cmap/auth/mongodb_oidc/human_callback_workflow.ts:134 and callback_workflow.ts:18. The driver aborts the callback via the provided AbortSignal and surfaces this as a MongoOIDCError. The human workflow is used for interactive flows where a user logs in (e.g. browser-based device-code or auth-code login).

Source

Thrown at src/cmap/auth/mongodb_oidc/human_callback_workflow.ts:134

    const controller = new AbortController();
    const params: OIDCCallbackParams = {
      timeoutContext: controller.signal,
      version: OIDC_VERSION,
      idpInfo: idpInfo
    };
    if (credentials.username) {
      params.username = credentials.username;
    }
    if (refreshToken) {
      params.refreshToken = refreshToken;
    }
    const timeout = Timeout.expires(HUMAN_TIMEOUT_MS);
    try {
      return await Promise.race([this.executeAndValidateCallback(params), timeout]);
    } catch (error) {
      if (TimeoutError.is(error)) {
        controller.abort();
        throw new MongoOIDCError(`OIDC callback timed out after ${HUMAN_TIMEOUT_MS}ms.`);
      }
      throw error;
    } finally {
      timeout.clear();
    }
  }
}

View on GitHub (pinned to 3366c21a63)

Solutions

  1. Ensure the end user completes the interactive login within 5 minutes.
  2. Honor params.timeoutContext (AbortSignal) in the callback so the work is cancelled promptly on timeout.
  3. For non-interactive contexts, use the automated/machine workflow (ENVIRONMENT) or a custom machine callback rather than a human callback.
  4. Improve callback latency by pre-opening the browser or using device-code flows that return quickly.

Example fix

// before: human callback blocks on user input with no signal handling
const humanCb = async (params) => {
  const code = await waitForUserToEnterCode(); // blocks indefinitely
  return exchangeCode(code);
};

// after: honor the abort signal
const humanCb = async (params) => {
  const code = await waitForUserToEnterCode(params.timeoutContext);
  if (params.timeoutContext.aborted) throw new Error('aborted');
  return exchangeCode(code);
};
Defensive patterns

Strategy: try-catch

Validate before calling

function assertHumanCallbackHonorsSignal(cb: (p: any) => Promise<any>): Promise<void> {
  const ac = new AbortController();
  setTimeout(() => ac.abort(), 1000);
  return cb({ timeoutContext: ac.signal, version: 1 }).then(
    () => { /* ok */ },
    e => { if (!/aborted/i.test(String(e))) throw new Error('Human callback ignored abort signal'); }
  );
}

Try / catch

try {
  await client.connect();
} catch (e) {
  if (e instanceof MongoOIDCError && /OIDC callback timed out/.test(e.message)) {
    log.warn('Human OIDC login timed out; prompt user to complete within 5 minutes');
  }
  throw e;
}

Prevention

When it happens

Trigger: Connecting with MONGODB-OIDC using a human/interactive callback that does not resolve within 5 minutes. Commonly the callback waits on user interaction (entering a code in a browser) that never completes, or performs a slow IdP HTTP request that ignores params.timeoutContext.

Common situations: User closes the browser without completing login, the IdP is unreachable, the callback prompts the user but the prompt is non-interactive (CI), or the callback performs a long synchronous operation.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04). Data as JSON: /data/errors/c43eea4ecf8d22ba.json. Report an issue: GitHub.