{"record":{"id":"3d199496032ed20e","repo":"slopus/happy","slug":"authentication-failed-or-was-cancelled","errorCode":null,"errorMessage":"Authentication failed or was cancelled","messagePattern":"Authentication failed or was cancelled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/happy-cli/src/ui/auth.ts","lineNumber":267,"sourceCode":"/**\n * Ensure authentication and machine setup\n * This replaces the onboarding flow and ensures everything is ready\n */\nexport async function authAndSetupMachineIfNeeded(): Promise<{\n    credentials: Credentials;\n    machineId: string;\n}> {\n    logger.debug('[AUTH] Starting auth and machine setup...');\n\n    // Step 1: Handle authentication\n    let credentials = await readCredentials();\n    let newAuth = false;\n\n    if (!credentials) {\n        logger.debug('[AUTH] No credentials found, starting authentication flow...');\n        const authResult = await doAuth();\n        if (!authResult) {\n            throw new Error('Authentication failed or was cancelled');\n        }\n        credentials = authResult;\n        newAuth = true;\n    } else {\n        logger.debug('[AUTH] Using existing credentials');\n    }\n\n    // Make sure we have a machine ID\n    // Server machine entity will be created either by the daemon or by the CLI\n    const settings = await updateSettings(async s => {\n        if (newAuth || !s.machineId) {\n            return {\n                ...s,\n                machineId: randomUUID()\n            };\n        }\n        return s;\n    });","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/slopus/happy/blob/b824cd0a4681d41af631a8e422a813873e4455b0/packages/happy-cli/src/ui/auth.ts#L249-L285","documentation":"authAndSetupMachineIfNeeded starts the interactive authentication flow via doAuth() when no stored credentials exist. doAuth() resolves falsy when the user aborts the flow (closes browser, declines the prompt) or the auth handshake fails; the function then throws this error instead of continuing to set up a machine. It is a deliberate abort signal, not an internal fault.","triggerScenarios":"First run (or after credentials were removed) where doAuth() returns null/undefined: the user cancelled the browser login, the callback/redirect never completed, or the auth server rejected the flow.","commonSituations":"User closed the auth browser tab before completing login; headless/CI environment with no browser; callback port blocked or already in use; auth server returned an error and the flow swallowed it into a falsy result.","solutions":["Re-run the command and complete the browser login flow without closing the tab.","On headless machines, use the printed URL on a device with a browser and finish the handshake.","Ensure the local OAuth callback port is free and not firewalled.","Check auth server reachability; retry if a transient server error aborted the flow."],"exampleFix":"// before\n$ happy start   # (ctrl-C or closed browser tab) Authentication failed or was cancelled\n// after\n$ happy start   # complete the login in the browser window that opens","handlingStrategy":"try-catch","validationCode":"import { readLocalHappyAgentCredentials } from '...';\nif (readLocalHappyAgentCredentials()) {\n  // credentials exist — auth flow won't be needed\n}","typeGuard":null,"tryCatchPattern":"try {\n  await startSession();\n} catch (err) {\n  if ((err as Error).message === 'Authentication failed or was cancelled') {\n    console.error('Login cancelled. Re-run and complete the browser auth flow.');\n  } else throw err;\n}","preventionTips":["Complete the browser login; don't close the tab or abort the prompt.","On headless hosts, open the printed auth URL elsewhere and finish the handshake.","Ensure the OAuth callback port is free and permitted by the firewall.","Pre-authenticate in CI/headless environments before running session commands."],"tags":["auth","oauth","user-cancellation","cli"],"backgroundTag":"auth-cancelled","analyzedSha":"b824cd0a4681d41af631a8e422a813873e4455b0","analyzedAt":"2026-08-31T23:12:36.205Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}