← Back to PRs

#20390: fix(daemon): fall back to /tmp for launchd logs on removable volumes

by lemoz open 2026-02-18 21:17 View on GitHub →
gateway size: S
## Summary - macOS launchd refuses to redirect stdout/stderr to paths under `/Volumes/`, causing the LaunchAgent to fail with EPERM when `OPENCLAW_STATE_DIR` (or `~/.openclaw` via symlink) resolves to an external drive - Detects `/Volumes/` at plist-generation time via `realpathSync` and routes logs to `/tmp/openclaw/` instead - Respects `OPENCLAW_LOG_PREFIX` in the fallback path ## Motivation Running OpenClaw from an external SSD (e.g. a portable "seed" drive with all projects) is a valid setup, but `launchctl` silently refuses to write log files to removable volumes. This makes the gateway LaunchAgent fail to start with no obvious error. The fix keeps logs flowing by using `/tmp` as a safe fallback on macOS. ## Test plan - [x] Added 4 new tests covering: default paths, `/Volumes` fallback, custom prefix with fallback, and non-`/Volumes` passthrough - [x] All 14 tests pass (`vitest run src/daemon/launchd.test.ts`) - [x] Lint passes 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR fixes a macOS-specific issue where `launchd` refuses to redirect stdout/stderr to paths on removable volumes (`/Volumes/...`), causing the gateway LaunchAgent to fail silently with EPERM when `OPENCLAW_STATE_DIR` (or `~/.openclaw` via symlink) resolves to an external drive. - Adds `realpathSync` check in `resolveGatewayLogPaths` to detect when the state directory resolves to `/Volumes/...` on macOS, falling back to `/tmp/openclaw/` for log paths - Respects `OPENCLAW_LOG_PREFIX` in the fallback path - Silently catches `realpathSync` errors (e.g., path doesn't exist yet) and defaults to the standard state-dir-based log location - Adds 4 new tests covering default paths, `/Volumes/` fallback, custom prefix with fallback, and non-`/Volumes/` passthrough (2 tests skip on non-darwin platforms) <h3>Confidence Score: 5/5</h3> - This PR is safe to merge — it addresses a real macOS limitation with a well-scoped, defensive fix. - The change is narrowly scoped to a single function (`resolveGatewayLogPaths`), guarded by a platform check (`darwin` only), and handles errors gracefully. The `/Volumes/` detection via `realpathSync` is the correct approach for catching symlinked state directories. All consumers of `resolveGatewayLogPaths` (install, diagnostics, status) will benefit transparently. No existing behavior changes for non-`/Volumes/` setups. Tests cover the key scenarios. - No files require special attention. <sub>Last reviewed commit: 7e15a5b</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs