eyaltoledano/claude-task-master · error · AuthenticationError
START_FLOW_FAILED
START_FLOW_FAILED
Error message
startResponse.message || 'Failed to start authentication flow'
What it means
During authenticateWithBackendPKCE the client generates an RSA keypair, then asks the backend to start a PKCE auth flow (startBackendFlow). If the backend response is unsuccessful or lacks a flow_id, the client throws AuthenticationError with code START_FLOW_FAILED, using the backend's message when provided.
Source
Thrown at packages/tm-core/src/modules/auth/services/oauth-service.ts:162
options: OAuthFlowOptions
): Promise<AuthCredentials> {
const {
openBrowser,
timeout = 300000,
onAuthUrl,
onWaitingForAuth,
onSuccess
} = options;
// Step 1: Generate keypair for E2E encryption
this.keyPair = generateKeyPair();
this.logger.debug('Generated RSA keypair for E2E encryption');
// Step 2: Start the flow on the backend with our public key
const startResponse = await this.startBackendFlow();
if (!startResponse.success || !startResponse.flow_id) {
throw new AuthenticationError(
startResponse.message || 'Failed to start authentication flow',
'START_FLOW_FAILED'
);
}
const { flow_id, verification_url, poll_interval = 2 } = startResponse;
// Store the auth URL
this.authorizationUrl = verification_url || null;
// Notify about the auth URL
if (onAuthUrl && verification_url) {
onAuthUrl(verification_url);
}
// Step 3: Open browser with verification URL
if (openBrowser && verification_url) {
try {View on GitHub (pinned to c0c98d367c)
Solutions
- Verify the backend base URL/configuration is correct and the server is reachable (curl the /api/auth/cli/start endpoint)
- Check the thrown message for backend-provided details and follow them
- Retry after a short delay if it was transient (5xx/network); check backend service health
- Update the CLI if the backend auth API version changed
- Catch AuthenticationError code START_FLOW_FAILED and surface startResponse.message to the user
Example fix
// before
await auth.authenticate(); // opaque START_FLOW_FAILED
// after
try {
await auth.authenticate();
} catch (e) {
if (e instanceof AuthenticationError && e.code === 'START_FLOW_FAILED') {
console.error('Auth backend rejected flow start:', e.message);
}
throw e;
} Defensive patterns
Strategy: retry
Validate before calling
// preflight: confirm the auth backend is reachable
const res = await fetch(`${baseUrl}/api/auth/cli/start`, { method: 'HEAD' }).catch(() => null);
if (!res) throw new Error('Auth backend unreachable at ' + baseUrl); Type guard
function isStartFlowFailed(e: unknown): e is AuthenticationError {
return e instanceof AuthenticationError && e.code === 'START_FLOW_FAILED';
} Try / catch
for (let i = 0; i < 3; i++) {
try { await auth.authenticate(); break; }
catch (e) {
if (isStartFlowFailed(e) && i < 2) { await sleep(2000 * (i + 1)); continue; }
throw e;
}
} Prevention
- Verify the backend base URL matches the deployed API version
- Add a reachability preflight before login flows
- Implement bounded retries with backoff for transient backend failures
- Surface the backend-provided message (startResponse.message) in CLI output for diagnostics
When it happens
Trigger: POST to `${baseUrl}/api/auth/cli/start` returns success=false, an error payload, or a 2xx body without flow_id — e.g. backend outage, unsupported server version, rate limiting, or wrong base URL hitting an unexpected endpoint.
Common situations: Pointing tm at a stale/mismatched backend URL; API server down or deployed with a different auth API; corporate proxy intercepting the request; backend rate-limits repeated login attempts.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/a994fad48af82476.
Report an issue: GitHub.