{"record":{"id":"986f68b8204173fa","repo":"coleam00/Archon","slug":"failed-to-start-subscription-login","errorCode":null,"errorMessage":"Failed to start subscription login","messagePattern":"Failed to start subscription login","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"packages/server/src/routes/api.ts","lineNumber":2065,"sourceCode":"      );\n    }\n    try {\n      const start = await startOAuth(web.userId, provider);\n      return c.json(start);\n    } catch (err) {\n      // A leaked callback port from a previous attempt is an expected,\n      // retryable condition — log it at warn under its own event (an\n      // error-level `…_failed` would pollute error dashboards on multi-user\n      // installs) and surface the actionable message as a 503 instead of an\n      // opaque 500 (#1963).\n      if (err instanceof OAuthCallbackPortBusyError) {\n        getLog().warn({ userId: web.userId, provider }, 'auth.provider_oauth_start_port_busy');\n        return apiError(c, 503, err.message);\n      }\n      getLog().error(\n        { err: err as Error, userId: web.userId, provider },\n        'auth.provider_oauth_start_failed'\n      );\n      return apiError(c, 500, 'Failed to start subscription login');\n    }\n  });\n\n  registerOpenApiRoute(providerOAuthPollRoute, async c => {\n    const web = await requireWebUser(c, 'Web authentication required to connect a subscription');\n    if ('error' in web) return web.error;\n    if (!isPerUserProviderKeysEnabled()) {\n      return apiError(c, 404, 'Per-user provider keys are not enabled on this install');\n    }\n    // The `:provider` path segment only keeps the OAuth routes under one prefix\n    // (so they're exempt from the Better Auth catch-all); poll itself keys off\n    // sessionId + userId.\n    const { sessionId, code } = getValidatedBody(c, providerOAuthPollBodySchema);\n    // pollOAuth is bound to the session's userId, so a stranger's sessionId resolves\n    // to an error status rather than another user's login.\n    const result = pollOAuth(sessionId, web.userId, code);\n    return c.json(result);","sourceCodeStart":2047,"sourceCodeEnd":2083,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/server/src/routes/api.ts#L2047-L2083","documentation":"Generic failure branch of the provider OAuth subscription-login start route. Any error starting the OAuth flow that is NOT OAuthCallbackPortBusyError is logged at error level (auth.provider_oauth_start_failed, with err and provider attached) and returned as HTTP 500 with this opaque message, so provider-specific detail stays in server logs rather than the response.","triggerScenarios":"Any exception in the OAuth-start path besides port-busy: provider SDK failing to build the auth URL, credential/subscription not found or invalid, callback-server construction throwing for a non-port reason, or an unexpected internal error.","commonSituations":"Provider CLI/SDK not installed or its config missing for the requested provider; expired or revoked provider credentials; a bug/regression in the OAuth-start code path; environment misconfiguration on a fresh self-hosted install.","solutions":["Check server logs for the auth.provider_oauth_start_failed entry — the err object carries the root cause (message/stack).","Verify the provider is properly set up (its CLI authenticated or config file present) before retrying the login.","Re-authenticate or refresh the provider credentials for that userId.","Retry once; if persistent, run the provider login manually outside the API to surface the real error, then report it if it is engine-side."],"exampleFix":"// diagnose from the response alone? Instead read the server log:\n// getLog().error({ err, userId, provider }, 'auth.provider_oauth_start_failed')\n$ grep provider_oauth_start_failed server.log | jq '.err.message'","handlingStrategy":"try-catch","validationCode":"// before calling the API, confirm the provider is set up\nimport { existsSync } from 'node:fs';\nif (!existsSync(providerConfigPath(provider))) {\n  throw new Error(`Provider ${provider} is not configured; run its native login first`);\n}","typeGuard":"function isOAuthStartFailed(res: { status: number; error?: string }): res is { status: 500; error: 'Failed to start subscription login' } {\n  return res.status === 500 && res.error === 'Failed to start subscription login';\n}","tryCatchPattern":"try {\n  await startProviderOAuth(provider);\n} catch (err) {\n  // response is intentionally opaque; read server log event for cause\n  const cause = await readServerLogEvent('auth.provider_oauth_start_failed');\n  throw new Error(`OAuth start failed: ${cause ?? err.message}`);\n}","preventionTips":["Authenticate the provider via its native CLI/config before using the subscription-login route.","Check the auth.provider_oauth_start_failed log entry for the err detail instead of relying on the generic 500 body.","Re-run the provider login after any credential rotation or expiry.","Report persistent failures with the log entry; the response alone cannot identify the cause."],"tags":["oauth","http-500","provider-auth","internal-error"],"backgroundTag":"oauth-flow-start-failed","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}