#22896: Handle Slack SDK .original in transient network detection
size: S
Cluster:
Slack Gateway Error Handling
## Summary
Fixes the gateway crash loop caused by Slack DNS failures. The `@slack/web-api` SDK wraps network errors in a custom error shape with `.original` containing the underlying error, but the existing `isTransientNetworkError()` only checked `.cause`. This caused `ENOTFOUND` errors to be unrecognized and trigger `process.exit(1)`.
## Changes
- Add `.original` recursion in `isTransientNetworkError()` to handle Slack SDK error wrapping
- Add `extractTransientNetworkCode()` helper to extract inner error codes for logging
- Add explicit guard against `slack_webapi_platform_error` to ensure auth failures are never suppressed
- Update log message to show inner error code: `[openclaw] Non-fatal unhandled rejection (continuing) [ENOTFOUND]:`
- Add unit tests for Slack SDK wrapper patterns
- Add integration test confirming no-exit behavior
## Root Cause
When DNS fails, the Slack SDK creates:
```javascript
{
code: "slack_webapi_request_error",
message: "A request error occurred: getaddrinfo ENOTFOUND slack.com",
original: {
code: "ENOTFOUND", // ← The real error is here
message: "getaddrinfo ENOTFOUND slack.com"
}
}
```
The handler checked `.cause` but not `.original`, so `ENOTFOUND` was never found → error classified as unknown → `process.exit(1)` → launchd respawn → repeat.
## Verification
1. Start gateway with Slack configured
2. Disable Wi-Fi or break DNS (`sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder`)
3. Confirm no restart loop (`launchctl print gui/$(id -u)/ai.openclaw.gateway | grep runs`)
4. Confirm CLI/dashboard still work: `openclaw gateway probe`
5. Check logs show: `grep "Non-fatal unhandled rejection (continuing) \[ENOTFOUND\]" ~/.openclaw/logs/gateway.log`
6. Restore network → Slack reconnects automatically
## Related Issues
- Closes root cause of #22865 (Slack crash loop)
- Mitigates #22866 (pairing token corruption) by preventing the launchd restart loops that trigger token invalidation — but does not directly fix the token persistence issue
## Notes
This change does NOT widen the existing `TRANSIENT_NETWORK_CODES` set. It only makes the existing policy apply correctly to Slack's wrapped error shape.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Adds `.original` property recursion to `isTransientNetworkError()` to handle `@slack/web-api` SDK error wrapping. The Slack SDK wraps underlying network errors (like `ENOTFOUND`) in a custom error shape with the real error in `.original`, but the existing handler only checked `.cause`. This caused DNS failures to be misclassified and trigger `process.exit(1)`.
- Adds recursive `.original` checking in both `isTransientNetworkError()` and new `extractTransientNetworkCode()` helper
- Includes explicit guard against `slack_webapi_platform_error` to ensure auth failures are never suppressed
- Updates log messages to show inner error codes (e.g., `[ENOTFOUND]`) for better debugging
- Comprehensive test coverage for Slack SDK wrapper patterns across multiple transient error codes
- Integration test confirms no-exit behavior for wrapped errors
<h3>Confidence Score: 5/5</h3>
- Safe to merge - focused bug fix with excellent test coverage and no behavioral changes to existing error handling
- The implementation is well-designed with proper circular reference guards, comprehensive test coverage across multiple scenarios, and an explicit safety guard for platform errors. The change only affects error detection logic for wrapped errors and doesn't widen the set of suppressed error codes.
- No files require special attention
<sub>Last reviewed commit: 44f3d31</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
#23787: Handle transient Slack request errors without crashing the gateway
by graysurf · 2026-02-22
85.6%
#21163: Prevent Slack DNS errors from crashing the gateway
by graysurf · 2026-02-19
81.7%
#22096: fix(slack): traverse .original for Slack SDK errors; pass recipient...
by maiclaw · 2026-02-20
80.1%
#17879: fix: prevent Slack auth errors from crashing the entire gateway
by zuyan9 · 2026-02-16
78.0%
#17758: Fix crash on transient Discord gateway zombie connection errors
by DoyoDia · 2026-02-16
72.6%
#12369: fix: register unhandled rejection handler for Slack monitor
by Yida-Dev · 2026-02-09
72.4%
#8024: fix(slack): resolve channel names via directory for cross-account m...
by emma-digital-assistant · 2026-02-03
72.4%
#7563: fix: expand transient network error detection
by kaigritun · 2026-02-03
71.6%
#19083: Slack: preserve per-thread context and consistent thread replies
by jkimbo · 2026-02-17
71.3%
#13489: fix: preserve Slack channel/user ID case in target normalization
by sandieman2 · 2026-02-10
71.3%