{"record":{"id":"36d8f0a9e777ab13","repo":"slopus/happy","slug":"daemon-spawned-sessions-cannot-use-local-interacti","errorCode":null,"errorMessage":"Daemon-spawned sessions cannot use local/interactive mode. Use --happy-starting-mode remote or spawn sessions directly from terminal.","messagePattern":"Daemon-spawned sessions cannot use local/interactive mode\\. Use --happy-starting-mode remote or spawn sessions directly from terminal\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/happy-cli/src/claude/runClaude.ts","lineNumber":89,"sourceCode":"    resolve: (value: { ok: true }) => void;\n    reject: (error: Error) => void;\n    timeout: ReturnType<typeof setTimeout>;\n};\n\nexport async function runClaude(credentials: Credentials, options: StartOptions = {}): Promise<void> {\n    logger.debug(`[CLAUDE] ===== CLAUDE MODE STARTING =====`);\n    logger.debug(`[CLAUDE] This is the Claude agent, NOT Gemini`);\n    \n    const workingDirectory = process.cwd();\n    const sessionTag = randomUUID();\n\n    // Log environment info at startup\n    logger.debugLargeJson('[START] Happy process started', getEnvironmentInfo());\n    logger.debug(`[START] Options: startedBy=${options.startedBy}, startingMode=${options.startingMode}`);\n\n    // Validate daemon spawn requirements - fail fast on invalid config\n    if (options.startedBy === 'daemon' && options.startingMode === 'local') {\n        throw new Error('Daemon-spawned sessions cannot use local/interactive mode. Use --happy-starting-mode remote or spawn sessions directly from terminal.');\n    }\n\n    // Set backend for offline warnings (before any API calls)\n    connectionState.setBackend('Claude');\n\n    // Create session service\n    const api = await ApiClient.create(credentials);\n\n    // Create a new session\n    let state: AgentState = {};\n\n    // Get machine ID from settings (should already be set up)\n    const settings = await readSettings();\n    let machineId = settings?.machineId\n    const sandboxConfig = options.noSandbox ? undefined : settings?.sandboxConfig;\n    const sandboxEnabled = Boolean(sandboxConfig?.enabled);\n    const initialPermissionMode = applySandboxPermissionPolicy(\n        resolveInitialClaudePermissionMode(options.permissionMode, options.claudeArgs),","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/slopus/happy/blob/b824cd0a4681d41af631a8e422a813873e4455b0/packages/happy-cli/src/claude/runClaude.ts#L71-L107","documentation":"runClaude validates the spawn configuration before creating a session: sessions started by the Happy daemon run without a TTY, so local/interactive mode (which requires an attached terminal) is invalid. This fail-fast check throws when startedBy='daemon' and startingMode='local'.","triggerScenarios":"A session is spawned via `happy daemon ...`/daemon scheduling while options.startingMode resolves to 'local' — e.g. daemon config requests local mode, or CLI flags/env set --happy-starting-mode local for a daemon-spawned session.","commonSituations":"Configuring the daemon to auto-start sessions that default to local mode; passing --happy-starting-mode local in a daemon wrapper script; upgrading the daemon and reusing an old config that predates this restriction.","solutions":["Start the daemon-spawned session with --happy-starting-mode remote.","Remove any local-mode default from the daemon session config.","Spawn the session directly from your terminal (plain `happy claude`) if you need interactive mode.","Check daemon logs/config for a stale startingMode setting."],"exampleFix":"// before\nhappy daemon start --happy-starting-mode local\n// after\nhappy daemon start --happy-starting-mode remote","handlingStrategy":"validation","validationCode":"const isDaemonSpawn = process.env.HAPPY_STARTED_BY === 'daemon';\nconst mode = process.env.HAPPY_STARTING_MODE ?? 'local';\nif (isDaemonSpawn && mode === 'local') throw new Error('Daemon sessions must use --happy-starting-mode remote');","typeGuard":"function isValidDaemonConfig(o: { startedBy: string; startingMode: string }): boolean {\n  return !(o.startedBy === 'daemon' && o.startingMode === 'local');\n}","tryCatchPattern":"try {\n  await runClaude(options);\n} catch (err) {\n  if ((err as Error).message.includes('Daemon-spawned sessions')) {\n    console.error('Daemon + local mode is unsupported. Rerun with: happy --happy-starting-mode remote');\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["Never set startingMode local in daemon session templates.","Default daemon configs to remote mode.","Document the constraint in wrapper scripts that invoke happy via the daemon.","Validate flags in launch scripts before invoking happy."],"tags":["configuration","daemon","cli"],"backgroundTag":"invalid-mode-combination","analyzedSha":"b824cd0a4681d41af631a8e422a813873e4455b0","analyzedAt":"2026-08-31T23:12:36.205Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}