slopus/happy · error

Authentication failed or was cancelled

Error message

Authentication failed or was cancelled

What it means

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.

Source

Thrown at packages/happy-cli/src/ui/auth.ts:267

/**
 * Ensure authentication and machine setup
 * This replaces the onboarding flow and ensures everything is ready
 */
export async function authAndSetupMachineIfNeeded(): Promise<{
    credentials: Credentials;
    machineId: string;
}> {
    logger.debug('[AUTH] Starting auth and machine setup...');

    // Step 1: Handle authentication
    let credentials = await readCredentials();
    let newAuth = false;

    if (!credentials) {
        logger.debug('[AUTH] No credentials found, starting authentication flow...');
        const authResult = await doAuth();
        if (!authResult) {
            throw new Error('Authentication failed or was cancelled');
        }
        credentials = authResult;
        newAuth = true;
    } else {
        logger.debug('[AUTH] Using existing credentials');
    }

    // Make sure we have a machine ID
    // Server machine entity will be created either by the daemon or by the CLI
    const settings = await updateSettings(async s => {
        if (newAuth || !s.machineId) {
            return {
                ...s,
                machineId: randomUUID()
            };
        }
        return s;
    });

View on GitHub (pinned to b824cd0a46)

Solutions

  1. Re-run the command and complete the browser login flow without closing the tab.
  2. On headless machines, use the printed URL on a device with a browser and finish the handshake.
  3. Ensure the local OAuth callback port is free and not firewalled.
  4. Check auth server reachability; retry if a transient server error aborted the flow.

Example fix

// before
$ happy start   # (ctrl-C or closed browser tab) Authentication failed or was cancelled
// after
$ happy start   # complete the login in the browser window that opens
Defensive patterns

Strategy: try-catch

Validate before calling

import { readLocalHappyAgentCredentials } from '...';
if (readLocalHappyAgentCredentials()) {
  // credentials exist — auth flow won't be needed
}

Try / catch

try {
  await startSession();
} catch (err) {
  if ((err as Error).message === 'Authentication failed or was cancelled') {
    console.error('Login cancelled. Re-run and complete the browser auth flow.');
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31). Data as JSON: /api/errors/3d199496032ed20e. Report an issue: GitHub.