eyaltoledano/claude-task-master · warning

No refresh token received from server - session refresh will

Error message

No refresh token received from server - session refresh will not work

What it means

During PKCE authentication the backend returned credentials without a refresh_token. The OAuth service still builds a session with the access token but warns that Supabase cannot manage token lifecycle without a refresh token, so session persistence and silent refresh will not work — the user will have to log in again when the access token expires.

Source

Thrown at packages/tm-core/src/modules/auth/services/oauth-service.ts:207

		}

		// Notify that we're waiting for authentication
		if (onWaitingForAuth) {
			onWaitingForAuth();
		}

		// Step 4: Poll for completion
		const credentials = await this.pollForCompletion(
			flow_id,
			poll_interval * 1000,
			timeout
		);

		// Set the session in Supabase client
		// Note: Only set session if we have a valid refresh token
		// Supabase requires a valid refresh_token to manage token lifecycle
		if (!credentials.refreshToken) {
			this.logger.warn(
				'No refresh token received from server - session refresh will not work'
			);
		}

		const session: Session = {
			access_token: credentials.token,
			refresh_token: credentials.refreshToken ?? '',
			expires_in: credentials.expiresAt
				? Math.floor(
						(new Date(credentials.expiresAt).getTime() - Date.now()) / 1000
					)
				: 3600,
			token_type: 'bearer',
			user: {
				id: credentials.userId,
				email: credentials.email,
				app_metadata: {},
				user_metadata: {},

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Check the backend/Supabase auth settings so the token exchange returns refresh_token and forward it in credentials.
  2. Update the OAuth client configuration (e.g. ensure offline access / refresh tokens are enabled for the provider).
  3. Verify the client parses credentials.refreshToken from the correct response field after API changes.
  4. Accept short sessions and force re-login on each token expiry if refresh tokens are intentionally unsupported.

Example fix

// before
return { token: data.access_token }; // refresh_token dropped
// after
return { token: data.access_token, refreshToken: data.refresh_token };
Defensive patterns

Strategy: validation

Validate before calling

if (!credentials.refreshToken) {
  console.warn('Session will not be refreshable; re-login will be required on token expiry.');
  // or abort: throw new Error('Backend did not return a refresh token');
}

Type guard

function isRefreshableCredentials(c) {
  return typeof c.token === 'string' && c.token.length > 0 &&
         typeof c.refreshToken === 'string' && c.refreshToken.length > 0;
}

Try / catch

try {
  await authService.authenticate();
} catch (err) {
  if (err instanceof AuthenticationError && /refresh token/i.test(err.message)) {
    promptReLogin(); // full login required since silent refresh is unavailable
  }
}

Prevention

When it happens

Trigger: Completing the OAuth PKCE flow (authenticateWithBackendPKCE) against a backend/Supabase project whose configuration omits refresh tokens — e.g. Supabase auth with a client that doesn't return refresh_token, a custom backend proxy that strips it, or non-refreshable grant types.

Common situations: Supabase project configured with short-lived JWTs and refresh tokens disabled; custom auth backend forwarding only access_token; third-party OAuth provider misconfiguration; API version drift where the token exchange response schema changed.

Related errors


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