{"id":"645e2f05c8eb935e","repo":"redis/node-redis","slug":"tokenmanager-is-not-running-but-received-an-error","errorCode":null,"errorMessage":"TokenManager is not running but received an error: ${errorMessage}","messagePattern":"TokenManager is not running but received an error: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/client/lib/authx/token-manager.ts","lineNumber":314,"sourceCode":"    }\n\n    this.listener = null;\n    this.currentToken = null;\n    this.retryAttempt = 0;\n  }\n\n  /**\n   * Returns the current token or null if no token is available.\n   */\n  public getCurrentToken(): Token<T> | null {\n    return this.currentToken;\n  }\n\n  private notifyError(error: unknown, isRetryable: boolean): void {\n    const errorMessage = error instanceof Error ? error.message : String(error);\n\n    if (!this.listener) {\n      throw new Error(`TokenManager is not running but received an error: ${errorMessage}`);\n    }\n\n    this.listener.onError(new IDPError(errorMessage, isRetryable));\n  }\n}","sourceCodeStart":296,"sourceCodeEnd":319,"githubUrl":"https://github.com/redis/node-redis/blob/bb5beb56578573910e2ee8f39681edc214c41398/packages/client/lib/authx/token-manager.ts#L296-L319","documentation":"notifyError() is called when a token refresh fails and (after classification) must deliver an IDPError to the listener. It guards that a listener still exists; if the manager was stopped between the failed request and this call, there is nowhere to deliver the error and the manager throws instead of silently swallowing it. The message embeds the underlying errorMessage for diagnosability.","triggerScenarios":"The identity provider rejects a request, the retry path or non-retryable path reaches notifyError, but dispose() ran in the meantime and nulled the listener; a fatal IDP error triggers stop() and a concurrent in-flight request then also fails and calls notifyError on the already-stopped manager.","commonSituations":"IDP outage during shutdown; cascading failures where the first error stops the manager and subsequent in-flight requests also fail; tests forcing IDP errors then immediately disposing.","solutions":["Treat this as a teardown-race signal: ensure in-flight requests are drained or their rejections ignored during dispose().","Do not act on the error (it is informational); the manager is already stopped.","If it surfaces in production outside shutdown, review the IDP error-handling path and report a lifecycle bug with the interleaving."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  // ... token refresh path\n} catch (err) {\n  if (err instanceof Error && /not running but received an error/.test(err.message)) {\n    // error arrived after dispose; informational only\n  } else throw err;\n}","preventionTips":["Treat this as a teardown-race signal, not a token failure.","Drain in-flight IDP requests during shutdown."],"tags":["authx","token-manager","lifecycle","error-handling"],"analyzedSha":"bb5beb56578573910e2ee8f39681edc214c41398","analyzedAt":"2026-08-03T19:09:15.686Z","schemaVersion":2}