{"record":{"id":"0255b3b73d7352a4","repo":"mongodb/node-mongodb-native","slug":"attempted-to-get-a-refresh-token-when-none-exists","errorCode":null,"errorMessage":"Attempted to get a refresh token when none exists.","messagePattern":"Attempted to get a refresh token when none exists\\.","errorType":"exception","errorClass":"MongoOIDCError","httpStatus":null,"severity":"error","filePath":"src/cmap/auth/mongodb_oidc/token_cache.ts","lineNumber":34,"sourceCode":"\n  get hasRefreshToken(): boolean {\n    return !!this.refreshToken;\n  }\n\n  get hasIdpInfo(): boolean {\n    return !!this.idpInfo;\n  }\n\n  getAccessToken(): string {\n    if (!this.accessToken) {\n      throw new MongoOIDCError('Attempted to get an access token when none exists.');\n    }\n    return this.accessToken;\n  }\n\n  getRefreshToken(): string {\n    if (!this.refreshToken) {\n      throw new MongoOIDCError('Attempted to get a refresh token when none exists.');\n    }\n    return this.refreshToken;\n  }\n\n  getIdpInfo(): IdPInfo {\n    if (!this.idpInfo) {\n      throw new MongoOIDCError('Attempted to get IDP information when none exists.');\n    }\n    return this.idpInfo;\n  }\n\n  put(response: OIDCResponse, idpInfo?: IdPInfo) {\n    this.accessToken = response.accessToken;\n    this.refreshToken = response.refreshToken;\n    this.expiresInSeconds = response.expiresInSeconds;\n    if (idpInfo) {\n      this.idpInfo = idpInfo;\n    }","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/cmap/auth/mongodb_oidc/token_cache.ts#L16-L52","documentation":"Internal invariant of TokenCache (token_cache.ts:34): getRefreshToken() was called while refreshToken is undefined. The human workflow checks hasRefreshToken before calling getRefreshToken, so this throw should be unreachable through the public API. Reaching it implies a cache-state bug in the driver or direct use of the @internal TokenCache.","triggerScenarios":"Calling the internal TokenCache.getRefreshToken() without the hasRefreshToken guard; or a regression where a workflow path calls getRefreshToken after removeRefreshToken cleared it.","commonSituations":"Misuse of internal APIs in a forked/custom auth provider. A driver regression in the human callback workflow's refresh-token branch.","solutions":["File a driver bug if reached via the public API with a reproduction","When using internal APIs, check cache.hasRefreshToken before cache.getRefreshToken()","Upgrade the driver in case the regression is already fixed"],"exampleFix":"// before\nconst rt = cache.getRefreshToken();\n\n// after\nconst rt = cache.hasRefreshToken ? cache.getRefreshToken() : undefined;","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function getRefreshTokenSafe(cache: TokenCache): string | undefined {\n  return cache.hasRefreshToken ? cache.getRefreshToken() : undefined;\n}","tryCatchPattern":null,"preventionTips":["Use the public API; the workflows already guard getRefreshToken with hasRefreshToken","In forks, always check hasRefreshToken before getRefreshToken","Report regressions with a reproduction rather than working around the invariant"],"tags":["oidc","internal","invariant","token-cache"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}