{"record":{"id":"8d2875d5576e2c88","repo":"slopus/happy","slug":"failed-to-logout-error-instanceof-error-error","errorCode":null,"errorMessage":"Failed to logout: ${error instanceof Error ? error.message : 'Unknown error'}","messagePattern":"Failed to logout: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/happy-cli/src/commands/auth.ts","lineNumber":159,"sourceCode":"  rl.close();\n\n  if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {\n    try {\n      // Stop daemon if running\n      try {\n        await stopDaemon();\n        console.log(chalk.gray('Stopped daemon'));\n      } catch { }\n\n      // Remove entire happy directory (as current logout does)\n      if (existsSync(happyDir)) {\n        rmSync(happyDir, { recursive: true, force: true });\n      }\n\n      console.log(chalk.green('✓ Successfully logged out'));\n      console.log(chalk.gray('  Run \"happy auth login\" to authenticate again'));\n    } catch (error) {\n      throw new Error(`Failed to logout: ${error instanceof Error ? error.message : 'Unknown error'}`);\n    }\n  } else {\n    console.log(chalk.blue('Logout cancelled'));\n  }\n}\n\nasync function handleAuthStatus(): Promise<void> {\n  const credentials = await readCredentials();\n  const settings = await readSettings();\n\n  console.log(chalk.bold('\\nAuthentication Status\\n'));\n\n  if (!credentials) {\n    console.log(chalk.red('✗ Not authenticated'));\n    console.log(chalk.gray('  Run \"happy auth login\" to authenticate'));\n    return;\n  }\n","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/slopus/happy/blob/b824cd0a4681d41af631a8e422a813873e4455b0/packages/happy-cli/src/commands/auth.ts#L141-L177","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the wrapped message to see if it's a filesystem (EPERM/EBUSY) or network error","Close other happy processes/daemons (`happy daemon stop`) and retry logout","Manually remove the credentials directory (e.g. rm -rf ~/.happy) if deletion keeps failing","For network errors, note local credentials may already be cleared; re-login when back online"],"exampleFix":"// before\n$ happy auth logout\nError: Failed to logout: EPERM: operation not permitted, unlink '~/.happy/access.key'\n\n// after\n$ happy daemon stop\n$ happy auth logout   # or: rm -rf ~/.happy && happy auth login","handlingStrategy":"try-catch","validationCode":"import { accessSync, constants } from 'node:fs';\ntry {\n  accessSync(happyDir, constants.W_OK);\n} catch {\n  console.error('Cannot write to auth directory; fix permissions on ' + happyDir);\n  process.exit(1);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await handleAuthLogout(argv);\n} catch (error) {\n  const msg = (error as Error).message;\n  if (msg.includes('EPERM') || msg.includes('EBUSY')) {\n    console.error('Close other happy processes and retry logout.');\n  } else if (msg.includes('network') || msg.includes('fetch')) {\n    console.warn('Server revocation failed; local credentials may already be removed.');\n  } else { throw error; }\n}","preventionTips":["Stop the happy daemon before logging out","Ensure the auth directory (~/.happy) is writable and not on a read-only mount","Treat logout as idempotent: missing credentials should not be an error"],"tags":["auth","logout","filesystem","error-wrapping"],"backgroundTag":"logout-failed","analyzedSha":"b824cd0a4681d41af631a8e422a813873e4455b0","analyzedAt":"2026-08-31T23:12:36.205Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}