eyaltoledano/claude-task-master · error · AuthenticationError

POLL_FAILED

POLL_FAILED

Error message

errorData.message || `HTTP ${response.status}`

What it means

AuthenticationError thrown when the flow-status poll returns any non-2xx, non-404 status. It carries the server-provided error message when the body parses as JSON, otherwise the raw HTTP status, and terminates the polling loop for the authentication flow.

Solutions

  1. Read the message (server error text or HTTP status) and address the indicated cause server-side.
  2. On 429, increase the polling interval or reduce concurrent logins, then retry the flow.
  3. On 5xx, retry after a short wait or restart the authentication flow if the backend remains unhealthy.
  4. Check backend/gateway logs around the failure time to identify the upstream error.
  5. Confirm no auth middleware in front of /api/auth/cli/status is rejecting unauthenticated CLI requests.

Example fix

// before: aggressive polling
await oauth.pollForCompletion(flowId, 60000); // polls every ~1s -> 429 POLL_FAILED
// after: catch, inspect status, retry with backoff or restart
try {
  await oauth.pollForCompletion(flowId, 60000);
} catch (e) {
  if (e.code === 'POLL_FAILED' && e.message.includes('429')) {
    await new Promise(r => setTimeout(r, 5000));
    await oauth.pollForCompletion(flowId, 60000);
  }
}
Defensive patterns

Strategy: try-catch

Type guard

function isPollFailed(e: unknown): e is AuthenticationError {
  return e instanceof AuthenticationError && (e as any).code === 'POLL_FAILED';
}

Try / catch

try {
  await oauth.pollForCompletion(flowId, timeout);
} catch (e) {
  if (isPollFailed(e)) {
    if (/429/.test(e.message)) {
      await new Promise(r => setTimeout(r, 5000)); // back off on rate limit
    } else {
      console.error(`Poll failed: ${e.message} — check auth server health`);
    }
  }
}

Prevention

When it happens

Trigger: pollForCompletion receives response.ok === false with a status other than 404 — e.g. 401 from expired proxy credentials, 429 rate limiting from polling too aggressively, 500/502/503 from backend errors or a failing proxy.

Common situations: Long polling intervals too short hitting server rate limits; backend deployment or outage mid-login; gateway/ingress returning 502 during upstream restarts; auth service requiring a session/cookie the CLI doesn't send.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

					method: 'GET',
					headers: {
						'User-Agent': `TaskMasterCLI/${this.getCliVersion()}`
					}
				});

				if (!response.ok) {
					const errorData = (await response.json().catch(() => ({}))) as {
						message?: string;
					};

					if (response.status === 404) {
						throw new AuthenticationError(
							'Authentication flow expired or not found',
							'FLOW_NOT_FOUND'
						);
					}

					throw new AuthenticationError(
						errorData.message || `HTTP ${response.status}`,
						'POLL_FAILED'
					);
				}

				const data = (await response.json()) as FlowStatusResponse;

				if (!data.success) {
					throw new AuthenticationError(
						data.message || 'Failed to check status',
						'POLL_FAILED'
					);
				}

				switch (data.status) {
					case 'complete': {
						// Decrypt tokens using our private key
						if (!data.encrypted_tokens) {

View on GitHub (pinned to c0c98d367c)