{"record":{"id":"b619dd51811a58ee","repo":"mastra-ai/mastra","slug":"login-cancelled-b619dd","errorCode":null,"errorMessage":"Login cancelled","messagePattern":"Login cancelled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"mastracode/sdk/src/auth/providers/openai-codex.ts","lineNumber":548,"sourceCode":"async function loginOpenAICodexDevice(options: {\n  onAuth: (info: { url: string; instructions?: string }) => void;\n  onProgress?: (message: string) => void;\n  signal?: AbortSignal;\n  sleep?: (ms: number) => Promise<void>;\n}): Promise<OAuthCredentials> {\n  const pending = await startCodexDeviceLogin({ signal: options.signal });\n  const sleep = options.sleep ?? (ms => new Promise<void>(resolve => setTimeout(resolve, ms)));\n\n  options.onAuth({\n    url: pending.url,\n    instructions: pending.instructions,\n  });\n\n  await sleep(pending.intervalMs);\n\n  while (true) {\n    if (options.signal?.aborted) {\n      throw new Error('Login cancelled');\n    }\n\n    const result = await pollCodexDeviceLogin(pending, { signal: options.signal });\n    if (result.status === 'complete') {\n      return result.credentials;\n    }\n    if (result.status === 'failed') {\n      throw new Error(result.error);\n    }\n\n    options.onProgress?.('Waiting for OpenAI Codex device authorization...');\n    await sleep(result.nextPollMs);\n  }\n}\n\n/**\n * Login with OpenAI Codex OAuth\n *","sourceCodeStart":530,"sourceCodeEnd":566,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/auth/providers/openai-codex.ts#L530-L566","documentation":"The AbortSignal passed to loginOpenAICodexDevice was aborted while the library was waiting between device-login poll attempts. The library checks options.signal.aborted at the top of each poll iteration and throws to let the caller cancel a pending login. This is intentional cancellation, not a fault in the flow.","triggerScenarios":"The caller's AbortController is aborted (e.g. user pressed Ctrl+C, UI timeout, component unmounted) while loginOpenAICodexDevice was sleeping between polls of the device-authorization endpoint.","commonSituations":"CLI login cancelled by the user; React component unmount aborting the signal; a parent operation timing out and aborting all child signals; CI job timeout aborting an interactive login.","solutions":["No fix needed if the cancellation was intentional — catch and treat as a normal exit.","If the login should continue, do not abort the signal you pass in options (pass a fresh controller).","For UIs, keep the AbortController alive for the full expected login duration (user must visit a browser, which can take minutes).","On catch, show the user_code/verification URL again and offer to restart the login rather than silently exiting."],"exampleFix":"// before: controller aborted too early\nconst controller = new AbortController();\nsetTimeout(() => controller.abort(), 5000); // 5s is too short\nawait loginOpenAICodexDevice({ signal: controller.signal });\n\n// after: allow enough time for browser login\nconst controller = new AbortController();\nsetTimeout(() => controller.abort(), 10 * 60 * 1000); // 10 minutes\ntry {\n  await loginOpenAICodexDevice({ signal: controller.signal });\n} catch (e) {\n  if (e.message === 'Login cancelled') return; // treat as user cancel\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"function isAborted(e: unknown): boolean {\n  return e instanceof Error && e.message === 'Login cancelled';\n}","typeGuard":"const isLoginCancelled = (e: unknown): e is Error =>\n  e instanceof Error && e.message === 'Login cancelled';","tryCatchPattern":"try {\n  await loginOpenAICodexDevice({ signal: controller.signal });\n} catch (e) {\n  if (isLoginCancelled(e)) {\n    console.log('Login cancelled by user.');\n    return;\n  }\n  throw e;\n}","preventionTips":["Give the abort signal a generous timeout (minutes, not seconds).","Abort only on genuine user cancel or unmount.","Do not share a short-lived controller across long login flows.","Treat this error as normal control flow, not a bug."],"tags":["abort","cancellation","oauth","device-login"],"backgroundTag":"operation-aborted","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}