eyaltoledano/claude-task-master · error · AuthenticationError

REFRESH_FAILED

REFRESH_FAILED

Error message

'Failed to refresh session'

What it means

AuthenticationError with code REFRESH_FAILED thrown by SessionManager.refreshToken when supabaseClient.refreshSession() resolves without a session. Supabase's auth call did not return a refreshable session, typically because the refresh token is missing, expired, or already revoked. The method exists for explicit refresh requests; Supabase normally refreshes automatically via the storage adapter.

Source

Thrown at packages/tm-core/src/modules/auth/services/session-manager.ts:180

			tokenType: 'standard',
			savedAt: new Date().toISOString(),
			selectedContext: context || undefined
		};
	}

	/**
	 * Refresh authentication token using Supabase session
	 * Note: Supabase handles token refresh automatically via the session storage adapter.
	 * This method is mainly for explicit refresh requests.
	 */
	async refreshToken(): Promise<AuthCredentials> {
		await this.waitForInitialization();
		try {
			// Use Supabase's built-in session refresh
			const session = await this.supabaseClient.refreshSession();

			if (!session) {
				throw new AuthenticationError(
					'Failed to refresh session',
					'REFRESH_FAILED'
				);
			}

			// Sync user info to context store
			this.contextStore.saveContext({
				userId: session.user.id,
				email: session.user.email
			});

			// Build credentials response
			const context = this.contextStore.getContext();
			const credentials: AuthCredentials = {
				token: session.access_token,
				refreshToken: session.refresh_token,
				userId: session.user.id,
				email: session.user.email,

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Run the full login flow (task-master auth login) to obtain a fresh session
  2. Clear stale stored credentials and re-authenticate
  3. Check system clock skew (NTP) if the token was recently issued
  4. Ensure no concurrent sessions are rotating the same refresh token

Example fix

// before: assuming refresh always works
const creds = await sessionManager.refreshToken();
// after: re-login on REFRESH_FAILED
try {
  const creds = await sessionManager.refreshToken();
} catch (e) {
  if (e instanceof AuthenticationError && e.code === 'REFRESH_FAILED') {
    await sessionManager.login(); // full re-authentication
  }
}
Defensive patterns

Strategy: fallback

Validate before calling

// check stored session expiry before attempting refresh
const creds = await sessionManager.getCachedCredentials?.();
if (creds?.expiresAt && new Date(creds.expiresAt) < new Date()) {
  await reauthenticate(); // session clearly expired
}

Type guard

function isRefreshFailed(e: unknown): e is AuthenticationError {
  return e instanceof AuthenticationError && e.code === 'REFRESH_FAILED';
}

Try / catch

try {
  await sessionManager.refreshToken();
} catch (e) {
  if (isRefreshFailed(e)) {
    await sessionManager.login(); // full re-auth fallback
  } else throw e;
}

Prevention

When it happens

Trigger: Calling refreshToken() when there is no persisted session, the refresh token has expired (Supabase default ~ at least one reuse window passed), the token was already used/rotated elsewhere, or the user was signed out server-side.

Common situations: Long-lived CLI installations where the session expired weeks ago; logging in on another machine invalidated the refresh token; clock skew on the local machine; clearing ~/.taskmaster auth storage while still calling authenticated commands.

Related errors


AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29). Data as JSON: /api/errors/524cf5dc94140d5e. Report an issue: GitHub.