CRITICAL FIX: Gateway was crashing every 30-50 minutes due to unhandled
fetch() promise rejections causing process termination.
Problem:
- Network fetch() failures (DNS, timeout, connection refused) caused
unhandled promise rejections
- Unhandled rejection handler in src/infra/unhandled-rejections.ts calls
process.exit(1) to prevent silent failures
- Gateway crashed 3 times today (08:12:53, 08:41:31, 09:31:55)
- All agents stopped responding on each crash
- Required manual restart
Root Cause:
- 88+ fetch() calls in codebase without proper error handling
- TypeError: fetch failed at node:internal/deps/undici/undici:15422:13
- No try/catch or .catch() handlers on many network requests
Solution:
- Created safeFetch() wrapper that NEVER throws
- Always resolves to result object (ok: true | false)
- Classifies errors by type (network/abort/timeout/unknown)
- Logs errors with context but keeps gateway running
- Provides convenience helpers: safeFetchText, safeFetchJson
Implementation:
- New file: src/infra/safe-fetch.ts (core wrapper)
- New file: src/infra/safe-fetch.test.ts (comprehensive tests)
- New file: docs/infra/safe-fetch.md (usage guide & migration)
- Modified: src/infra/update-check.ts (example migration)
Testing:
- Full test suite covers success, failures, timeouts, aborts
- Migration verified with update-check.ts as proof of concept
Next Steps:
- Gradually migrate high-risk fetch() calls to safeFetch()
- Priority areas: agents/tools/web-*.ts, providers/*.ts
- Consider making safeFetch the default for new code
This fix prevents immediate crashes but doesn't migrate all calls yet.
Gateway stability should improve significantly with this foundation.
- Add resumeArgs to DEFAULT_CLAUDE_BACKEND for proper --resume flag usage
- Fix gateway not preserving cliSessionIds/claudeCliSessionId in nextEntry
- Add test for CLI session ID preservation in gateway agent handler
- Update docs with new resumeArgs default
* fix(gateway): prevent auth bypass when behind unconfigured reverse proxy
When proxy headers (X-Forwarded-For, X-Real-IP) are present but
gateway.trustedProxies is not configured, the gateway now treats
connections as non-local. This prevents a scenario where all proxied
requests appear to come from localhost and receive automatic trust.
Previously, running behind nginx/Caddy without configuring trustedProxies
would cause isLocalClient=true for all external connections, potentially
bypassing authentication and auto-approving device pairing.
The gateway now logs a warning when this condition is detected, guiding
operators to configure trustedProxies for proper client IP detection.
Also adds documentation for reverse proxy security configuration.
* fix: harden reverse proxy auth (#1795) (thanks @orlyjamie)
---------
Co-authored-by: orlyjamie <orlyjamie@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* feat: audit fixes and documentation improvements
- Refactored model selection to drop legacy fallback and add warning
- Improved heartbeat content validation
- Added Skill Creation guide
- Updated CONTRIBUTING.md with roadmap
* style: fix formatting in model-selection.ts
* style: fix formatting and improve model selection logic with tests
Add documentation for running Clawdbot in a sandboxed macOS VM
using Lume. This provides an alternative to buying dedicated
hardware or using cloud instances.
The guide covers:
- Installing Lume on Apple Silicon Macs
- Creating and configuring a macOS VM
- Installing Clawdbot inside the VM
- Running headlessly for 24/7 operation
- iMessage integration via BlueBubbles
- Saving golden images for easy reset