openclaw - ✅(Solved) Fix Gateway crash: Agent listener invoked outside active run [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#62435Fetched 2026-04-08 03:04:20
View on GitHub
Comments
1
Participants
2
Timeline
3
Reactions
0
Timeline (top)
commented ×1cross-referenced ×1subscribed ×1

Error Message

Unhandled promise rejection: Error: Agent listener invoked outside active run at Agent.processEvents (pi-agent-core/src/agent.ts:533) at Object.onUpdate (pi-agent-core/src/agent-loop.ts:539) at emitUpdate (exec-defaults-uj0McX2k.js:1524) at handleStdout (exec-defaults-uj0McX2k.js:1546) at Object.onSupervisorStdout (exec-defaults-uj0McX2k.js:1610) at Socket.<anonymous> (exec-defaults-uj0McX2k.js:568)

PR fix notes

PR #62815: fix(exec): prevent gateway crash from agent listener error

Description (problem / solution / changelog)

Summary

Fixes critical gateway crash when subprocess stdout arrives after agent run ends, causing unhandled promise rejection "Agent listener invoked outside active run".

Changes:

  • Add try-catch wrapper around opts.onUpdate() in emitUpdate()
  • Add suppression flag to prevent repeated errors after first failure
  • Proactively disable updates when exec process completes
  • Add comprehensive test coverage (5 new tests, all passing)
  • Add detailed inline documentation explaining the race condition

Fixes

  • #62746 - Gateway crash: Unhandled promise rejection
  • #62520 - Background exec output after subagent run completes
  • #62477 - Subprocess stdout arrives after agent run ends
  • #61741 - Race condition in subagent/session cleanup
  • #62435 - Gateway crash: Agent listener invoked outside active run

Root Cause

Race condition between subprocess lifecycle (exec-runtime) and agent run lifecycle (pi-agent-core). When an agent run completes and clears activeRun, any subprocess still producing stdout triggers opts.onUpdate() which calls Agent.processEvents(). Since activeRun is undefined, it throws an error that becomes an unhandled promise rejection, crashing the gateway.

Solution

Defensive guard with smart suppression:

  1. Try-catch wrapper prevents crash
  2. Suppression flag stops repeated errors
  3. Proactive disabling in promise handlers
  4. Smart logging (warn first, debug subsequent)

Test Plan

  • ✅ All 5 new tests pass (race condition, suppression, PTY, normal operation, backgrounded)
  • ✅ All 164 existing bash-tools tests pass
  • ✅ Verified exec process continues normally after error suppression
  • ✅ Verified logging provides clear context

Impact

  • Prevents gateway crashes occurring every 20-30 minutes under multi-lane operation
  • Affects all platforms (Windows, macOS, Linux)
  • Affects all channels (Telegram, Discord, Slack, WhatsApp, CLI)
  • Resolves 20+ duplicate issues

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/agents/bash-tools.exec-runtime.ts (modified, +58/-11)
  • src/agents/bash-tools.exec.on-update-lifecycle.test.ts (added, +106/-0)
  • src/agents/bash-tools.exec.pty-cleanup.test.ts (modified, +6/-6)

Code Example

Unhandled promise rejection: Error: Agent listener invoked outside active run
    at Agent.processEvents (pi-agent-core/src/agent.ts:533)
    at Object.onUpdate (pi-agent-core/src/agent-loop.ts:539)
    at emitUpdate (exec-defaults-uj0McX2k.js:1524)
    at handleStdout (exec-defaults-uj0McX2k.js:1546)
    at Object.onSupervisorStdout (exec-defaults-uj0McX2k.js:1610)
    at Socket.<anonymous> (exec-defaults-uj0McX2k.js:568)
RAW_BUFFERClick to expand / collapse

Environment: macOS 26.3.1 · OpenClaw 2026.4.5 (3e72c03) · Node 25.6.1 Gateway: LaunchAgent, running at ws://127.0.0.1:18888


Incident

Gateway crashed at 16:52:43 GMT+8, recovered ~6s later. One Discord session became unresponsive (zombie state) while others continued normally.

Stack trace (gateway.err.log)

Unhandled promise rejection: Error: Agent listener invoked outside active run
    at Agent.processEvents (pi-agent-core/src/agent.ts:533)
    at Object.onUpdate (pi-agent-core/src/agent-loop.ts:539)
    at emitUpdate (exec-defaults-uj0McX2k.js:1524)
    at handleStdout (exec-defaults-uj0McX2k.js:1546)
    at Object.onSupervisorStdout (exec-defaults-uj0McX2k.js:1610)
    at Socket.<anonymous> (exec-defaults-uj0McX2k.js:568)

Pathway

  1. exec child process produced stdout
  2. handleStdout → emitUpdate → onUpdate tried to notify agent-loop
  3. Agent.processEvents detected listener called outside active run → thrown
  4. Unhandled rejection → gateway crashed

Secondary issue

Post-recovery, the affected session remained alive and queuing messages, but no worker consumed the queue. Gateway showed "ready" and responded to sessions.list. Only a new /new session resolved it.

Trigger conditions

  • exec stdout produced + gateway in specific internal state
  • Not easily reproducible deterministically

Notes

  • No custom hooks in the crash path (self-improvement hook loaded fine post-recovery)
  • This appears to be a pi-agent-core issue in the exec-defaults stdout handler

extent analysis

TL;DR

The gateway crash is likely caused by an unhandled promise rejection in the Agent.processEvents function, which can be mitigated by ensuring that the agent listener is only invoked within an active run.

Guidance

  • Review the pi-agent-core code, specifically the agent.ts and agent-loop.ts files, to understand the conditions under which the Agent.processEvents function is called outside of an active run.
  • Investigate the exec-defaults-uj0McX2k.js file to determine why the handleStdout function is emitting an update that triggers the onUpdate function outside of an active run.
  • Consider adding error handling to the Agent.processEvents function to catch and handle the promise rejection, preventing the gateway from crashing.
  • To resolve the secondary issue, explore why the affected session remains alive and queuing messages after the gateway recovers, and why a new session is required to resolve the issue.

Example

No code snippet is provided as the issue does not contain sufficient information to create a specific example.

Notes

The root cause of the issue appears to be related to the pi-agent-core code, specifically the handling of stdout events from the exec child process. The trigger conditions for the crash are not easily reproducible, which may make it challenging to debug and fix the issue.

Recommendation

Apply a workaround to handle the promise rejection in the Agent.processEvents function to prevent the gateway from crashing, while further investigating the root cause of the issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING