slopus/happy · error

Failed to logout: ${error instanceof Error ? error.message :

Error message

Failed to logout: ${error instanceof Error ? error.message : 'Unknown error'}

What it means

handleAuthLogout wraps any exception from the logout flow — removing credential files/directories, server session revocation — into 'Failed to logout: <message>'. It's an umbrella error: the local auth state may or may not have been cleared depending on where it failed.

Source

Thrown at packages/happy-cli/src/commands/auth.ts:159

  rl.close();

  if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
    try {
      // Stop daemon if running
      try {
        await stopDaemon();
        console.log(chalk.gray('Stopped daemon'));
      } catch { }

      // Remove entire happy directory (as current logout does)
      if (existsSync(happyDir)) {
        rmSync(happyDir, { recursive: true, force: true });
      }

      console.log(chalk.green('✓ Successfully logged out'));
      console.log(chalk.gray('  Run "happy auth login" to authenticate again'));
    } catch (error) {
      throw new Error(`Failed to logout: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  } else {
    console.log(chalk.blue('Logout cancelled'));
  }
}

async function handleAuthStatus(): Promise<void> {
  const credentials = await readCredentials();
  const settings = await readSettings();

  console.log(chalk.bold('\nAuthentication Status\n'));

  if (!credentials) {
    console.log(chalk.red('✗ Not authenticated'));
    console.log(chalk.gray('  Run "happy auth login" to authenticate'));
    return;
  }

View on GitHub (pinned to b824cd0a46)

Solutions

  1. Read the wrapped message to see if it's a filesystem (EPERM/EBUSY) or network error
  2. Close other happy processes/daemons (`happy daemon stop`) and retry logout
  3. Manually remove the credentials directory (e.g. rm -rf ~/.happy) if deletion keeps failing
  4. For network errors, note local credentials may already be cleared; re-login when back online

Example fix

// before
$ happy auth logout
Error: Failed to logout: EPERM: operation not permitted, unlink '~/.happy/access.key'

// after
$ happy daemon stop
$ happy auth logout   # or: rm -rf ~/.happy && happy auth login
Defensive patterns

Strategy: try-catch

Validate before calling

import { accessSync, constants } from 'node:fs';
try {
  accessSync(happyDir, constants.W_OK);
} catch {
  console.error('Cannot write to auth directory; fix permissions on ' + happyDir);
  process.exit(1);
}

Try / catch

try {
  await handleAuthLogout(argv);
} catch (error) {
  const msg = (error as Error).message;
  if (msg.includes('EPERM') || msg.includes('EBUSY')) {
    console.error('Close other happy processes and retry logout.');
  } else if (msg.includes('network') || msg.includes('fetch')) {
    console.warn('Server revocation failed; local credentials may already be removed.');
  } else { throw error; }
}

Prevention

When it happens

Trigger: The `happy auth logout` command's try block throws: rmSync failing on the happy dir (permissions, file locks), or an error while contacting the server to invalidate the session.

Common situations: Read-only filesystem or sandboxed environment blocking deletion of ~/.happy; another happy process holding files open (EBUSY/EPERM); network failure while revoking the session server-side.

Related errors


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