eyaltoledano/claude-task-master · error · AuthenticationError

SESSION_SET_FAILED

SESSION_SET_FAILED

Error message

Failed to set session: ${error.message}

What it means

In SupabaseClient.setSession(), when `client.auth.setSession({access_token, refresh_token})` returns an error from Supabase, it is wrapped as AuthenticationError with code SESSION_SET_FAILED. This means Supabase rejected the token pair being installed as the current session — typically because the refresh token is invalid, expired, or already used.

Source

Thrown at packages/tm-core/src/modules/integration/clients/supabase-client.ts:353

		} catch (error) {
			this.logger.error('Error during sign out:', error);
		}
	}

	/**
	 * Set session from external auth (e.g., from server callback)
	 */
	async setSession(session: Session): Promise<void> {
		const client = this.getClient();

		try {
			const { error } = await client.auth.setSession({
				access_token: session.access_token,
				refresh_token: session.refresh_token
			});

			if (error) {
				throw new AuthenticationError(
					`Failed to set session: ${error.message}`,
					'SESSION_SET_FAILED'
				);
			}

			this.logger.info('Session set successfully');
		} catch (error) {
			if (error instanceof AuthenticationError) {
				throw error;
			}

			throw new AuthenticationError(
				`Failed to set session: ${(error as Error).message}`,
				'SESSION_SET_FAILED'
			);
		}
	}

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Verify the tokens came from the same Supabase project configured in the client (URL and anon key match).
  2. Check the refresh token is still valid and unused — with rotating refresh tokens, only the latest token works; re-authenticate if it was already consumed.
  3. Ensure the session object passed in is complete (access_token and refresh_token both present and unmodified).
  4. Read error.message in the thrown error for the Supabase code and act on it (e.g. refresh_token_not_found → new login).

Example fix

// before
await client.setSession(oldCapturedSession);
// after
if (!oldCapturedSession?.access_token || !oldCapturedSession?.refresh_token) {
  throw new Error('Incomplete session; run login again');
}
try {
  await client.setSession(oldCapturedSession);
} catch (e) {
  // fall back to fresh login
}
Defensive patterns

Strategy: validation

Validate before calling

function canSetSession(s: unknown): s is Session {
  const x = s as Partial<Session> | null;
  return !!x && typeof x.access_token === 'string' && x.access_token.length > 0 &&
         typeof x.refresh_token === 'string' && x.refresh_token.length > 0;
}
if (!canSetSession(incomingSession)) throw new Error('Incomplete session tokens');
await client.setSession(incomingSession);

Type guard

function isSession(s: unknown): s is Session {
  const x = s as Record<string, unknown> | null;
  return !!x && typeof x.access_token === 'string' && typeof x.refresh_token === 'string';
}

Try / catch

try {
  await client.setSession(session);
} catch (e) {
  if (e instanceof AuthenticationError && e.code === 'SESSION_SET_FAILED') {
    // tokens rejected: clear state and force fresh login
    await client.signOut();
  } else throw e;
}

Prevention

When it happens

Trigger: Calling setSession(session) with a Session whose access_token/refresh_token Supabase refuses: refresh_token_not_found, invalid refresh token, or a token from a different project/instance.

Common situations: Passing a session captured from another environment (staging vs prod project); reusing a refresh token after Supabase rotated/invalidated it (single-use refresh tokens enabled); server callback handing over a truncated or stale session; SUPABASE_URL/KEY pointing to a different project than the one that issued the tokens.

Related errors


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