fix(pi-extension): don't crash pi on stale ctx in _emitRelayState - #80
Merged
jacobaraujo7 merged 1 commit intoAug 6, 2026
Merged
Conversation
_emitRelayState can run inside a WebSocket 'close' callback (via _onRelayClose). After a session replacement (newSession/fork/ switchSession/reload) the module-level _pi is stale, and sendMessage synchronously throws assertActive. With no try/catch on the WS event path, the throw becomes a process-level uncaughtException and exits pi. Wrap the sendMessage call in try/catch. The next relay-state change re-emits, so connectivity stays eventually consistent. Mirrors the stale-ctx tolerance already used by _ctxUi/_safeNotify (jacobaraujo7#55).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
piexits with an uncaught exception when the relay WebSocket closes after a session replacement:_emitRelayStateis reachable from a WebSocket'close'callback (via_onRelayClose). Afterctx.newSession()/fork()/switchSession()/reload(), the module-level_piis stale, andsendMessagesynchronously throwsassertActive. With notry/catchon the WS event path, the throw becomes a process-leveluncaughtExceptionand pi exits.The optional chain
_pi?.sendMessage(...)only guards against_pibeingnull; it does not guard against a present-but-stale ctx.Fix
Wrap the existing
_pi?.sendMessage(...)call intry/catch. No behavior change on the happy path. When_piis stale (or the extension runtime is not yet bound), the throw is swallowed instead of crashing the process. The next relay-state change re-emits, so connectivity stays eventually consistent.This mirrors the stale-ctx tolerance already used by
_ctxUi/_safeNotify(#55): those also swallow stale-ctx throws so relay events don't take down pi.Scope
Minimal and intentionally narrow: only
_emitRelayStateis touched. Other_pi?.sendMessage(...)call sites are left as-is. If any of them is also reachable from an async/WS path after a session replacement, it can be patched the same way in a follow-up.The root cause (captured ctx going stale after session replacement) is an SDK constraint, not something this extension can fully solve; this PR just stops one concrete crash path.
Testing
node --checkon the builtdist/index.js(equivalent change) passes.try/catch; no types or new APIs are introduced.