#22424: fix: prevent crash when onUpdate is truthy but not callable (fixes #22206)
channel: discord
agents
size: XS
experienced-contributor
Cluster:
Update Handling Fixes
## Summary
Fixes #22206 — prevents gateway crash when `opts.onUpdate` is truthy but not a function during exec runtime.
## Problem
The crash occurred during boot-md gateway startup when:
1. Embedded agent run starts
2. Skills-remote probe times out
3. Supervisor stdout handler fires `emitUpdate()` after the `onUpdate` callback has been invalidated
4. The guard at line 335 used `if (!opts.onUpdate)` — a falsy check that doesn't catch truthy non-functions like `true` or `{}`
5. Line 340 attempts to call `opts.onUpdate({...})` → TypeError
## Root Cause Analysis
After extensive investigation, I could not find explicit code that sets `onUpdate` to `true` or `{}`. The issue appears to occur during race conditions in cleanup/teardown scenarios where:
- The process continues running and generating stdout
- The callback has been invalidated (possibly during abort/timeout/cleanup)
- But stdout arrives after invalidation
## History
This bug was introduced in b47fa9e71 (about 2 months ago) but remained latent until PR #20569 merged. That PR changed boot-md to run per-agent, significantly increasing the probability of hitting this race condition during gateway startup.
## Solution
Changed the guard from falsy check to typeof check:
```diff
- if (!opts.onUpdate) return;
+ if (typeof opts.onUpdate !== "function") return;
```
This is a defensive fix that prevents the crash regardless of how the callback becomes invalid. The trade-off (lost progress updates when callback is invalidated) is acceptable compared to the crash (restart loop until stale locks clear).
## Test Plan
- [x] Added regression tests in `bash-tools.exec-runtime.guard.test.ts`
- [x] Tests reproduce the crash with `onUpdate: true` and `onUpdate: {}`
- [x] Tests verify the fix prevents the crash
- [x] CI gate passed (pnpm build && pnpm check)
## Impact
- Eliminates restart loop on gateway startup when boot-md encounters timeouts
- No functional changes to normal operation (guard only triggers when callback is already corrupted)
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR fixes a crash in the bash exec runtime that occurred when `onUpdate` callback was truthy but not callable. The fix changes the guard from a falsy check (`if (!opts.onUpdate)`) to a proper type check (`if (typeof opts.onUpdate !== "function")`), preventing `TypeError` when the callback becomes invalidated during race conditions in cleanup/teardown scenarios.
- Fixed critical crash bug in `bash-tools.exec-runtime.ts:335` affecting gateway startup
- Added comprehensive regression tests covering `onUpdate: true` and `onUpdate: {}` scenarios
- Aligns with existing codebase patterns (27+ other `typeof ... !== "function"` checks found)
- Other file changes are formatting-only (import order via `oxfmt`)
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk
- The fix is a minimal, defensive guard change that prevents a crash without altering any functional behavior. The typeof check aligns with 27+ existing patterns in the codebase. Comprehensive regression tests verify the fix prevents the crash scenarios. The only substantive change is a single-line guard improvement; other changes are formatting-only.
- No files require special attention
<sub>Last reviewed commit: 1712851</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#22897: fix(exec): guard onUpdate callback type in runtime
by Phineas1500 · 2026-02-21
82.4%
#14564: fix(gateway): crashes on startup when tailscale meets non-loopback ...
by yinghaosang · 2026-02-12
77.9%
#18647: fix(agents): guard against undefined paths in injectedFiles
by kleinpanic · 2026-02-16
77.6%
#19088: fix(gateway): allow startup with unset mode and fix pairing for local…
by mdanassaif · 2026-02-17
77.1%
#4653: fix(gateway): improve crash resilience for mDNS and network errors
by AyedAlmudarra · 2026-01-30
77.1%
#21944: feat(gateway): crash-loop protection with escalating backoff
by Protocol-zero-0 · 2026-02-20
77.0%
#20355: fix(gateway): enforce commands.restart guard for config.apply and c...
by Clawborn · 2026-02-18
76.8%
#12498: fix: guard against incomplete onboarding adapters missing getStatus
by hakityc · 2026-02-09
76.3%
#6577: fix: add null checks for stdout/stderr when using inherit-stdio fal...
by ncmalan · 2026-02-01
76.2%
#18193: fix: default elevatedDefault to 'off' instead of 'on' (#18177)
by lailoo · 2026-02-16
75.9%