Bug
When logging.file is set to a tilde-prefixed path (e.g. ~/.openclaw/logs/gateway.log) in openclaw.json, the gateway crashes on startup with:
Gateway failed to start: Error: ENOENT: no such file or directory, mkdir '~/.openclaw/logs'
The gateway's resolveSettings() in src/logging/logger.ts reads logging.file from config via readLoggingConfig(), which bypasses the normalizeConfigPaths() pipeline. The raw tilde path is passed directly to fs.mkdirSync() at line 101, which doesn't expand ~.
Repro
openclaw config set logging.file '"~/.openclaw/logs/gateway.log"' --json
openclaw gateway run
# → crashes immediately with ENOENT
Root Cause
resolveSettings() uses the raw config value without tilde expansion:
const file = cfg?.file ?? defaultRollingPathForToday();
Then buildLogger() passes it directly to:
fs.mkdirSync(path.dirname(settings.file), { recursive: true });
Node.js fs APIs don't expand ~, so it tries to create a literal ~/.openclaw/logs directory.
Fix
Call expandHomePrefix() on the file path in resolveSettings():
import { expandHomePrefix } from "../infra/home-dir.js";
// ...
const rawFile = cfg?.file ?? defaultRollingPathForToday();
const file = expandHomePrefix(rawFile);
This aligns with how other config paths are normalized via normalizeConfigPaths().
Impact
- Gateway fails to start and cannot self-recover (launchd keeps retrying and failing)
- Can be triggered by the embedded agent running
openclaw config set logging.file "~/.openclaw/logs/..."
- Observed in production: agent modified config → gateway hot-reloaded → crashed → launchd restart loop
🤖 Generated with Claude Code
Bug
When
logging.fileis set to a tilde-prefixed path (e.g.~/.openclaw/logs/gateway.log) inopenclaw.json, the gateway crashes on startup with:The gateway's
resolveSettings()insrc/logging/logger.tsreadslogging.filefrom config viareadLoggingConfig(), which bypasses thenormalizeConfigPaths()pipeline. The raw tilde path is passed directly tofs.mkdirSync()at line 101, which doesn't expand~.Repro
Root Cause
resolveSettings()uses the raw config value without tilde expansion:Then
buildLogger()passes it directly to:Node.js
fsAPIs don't expand~, so it tries to create a literal~/.openclaw/logsdirectory.Fix
Call
expandHomePrefix()on the file path inresolveSettings():This aligns with how other config paths are normalized via
normalizeConfigPaths().Impact
openclaw config set logging.file "~/.openclaw/logs/..."🤖 Generated with Claude Code