Bug type
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
/compact invokes runtime.compactEmbeddedPiSession(...) without passing any abortSignal and without registering the compaction session into ACTIVE_EMBEDDED_RUNS. As a result neither chat.abort, abortEmbeddedPiRun(sessionId), nor /stop has any effect on an in-progress /compact; the user has no way to cancel until compactionTimeoutMs expires.
Steps to reproduce
- Start OpenClaw on a session that has accumulated enough messages for
/compact to take tens of seconds or longer.
- In the chat, send
/compact.
- While compaction is running, attempt to cancel via any available path:
chat.abort, abortEmbeddedPiRun(sessionId) (directly or via the globalThis[Symbol.for("openclaw.embeddedRunState")].activeRuns.get(sessionId).abort() side door), or /stop.
- Observe that the compaction continues regardless.
Expected behavior
Invoking any supported cancel path should interrupt the compaction within a few seconds, consistent with any other embedded agent run. The compaction session should also appear in ACTIVE_EMBEDDED_RUNS for the duration, so external observers can discover it.
Actual behavior
All cancel attempts are no-ops. abortEmbeddedPiRun(sessionId) returns false immediately because the compaction session was never registered. chat.abort similarly finds nothing in chatAbortControllers. The compaction only ends when it completes successfully or when compactionTimeoutMs fires.
OpenClaw version
2026.4.12
Operating system
Ubuntu 22.04.5 LTS on WSL2 (Linux 6.6.87.2-microsoft-standard-WSL2)
Install method
npm global
Model
N/A (compaction uses whatever model the session is configured with; the cancel bug is independent of model selection)
Provider / routing chain
N/A (cancel path is orthogonal to provider routing)
Additional provider/model setup details
N/A
Logs, screenshots, and evidence
src/auto-reply/reply/commands-compact.ts (the current /compact handler, approximately L72-145): the handler first invokes abortEmbeddedPiRun(sessionId) + waitForEmbeddedPiRunEnd(sessionId, 15_000) to stop the current run, then calls runtime.compactEmbeddedPiSession({...}) without an abortSignal argument and without calling setActiveEmbeddedRun for the compaction itself.
The type definition in src/agents/pi-embedded-runner/compact.types.ts:56 already declares:
abortSignal?: AbortSignal;
on CompactEmbeddedPiSessionParams, so the parameter surface is prepared; the command path is simply not wiring it up. src/agents/pi-embedded-runner/compact.ts:520 (prepareCompactionSessionAgent) already passes an internal runAbortController.signal to a sub-session, so the inner mechanics exist.
Impact and severity
- Affected: any user who invokes
/compact on a long-running or complex session.
- Severity: Medium. No data loss, no crash, but the user is locked out of progress until the compaction or its timeout completes. On slow providers or large sessions this can be several minutes.
- Frequency: Every
/compact that the user wants to abandon — for example when they realize they sent the command prematurely, or when compaction is visibly stuck.
- Consequence: User frustration, wasted tokens on an unwanted compaction, and in at least one downstream UX (CoClaw UI) an explicit "disable cancel button during /compact" workaround to prevent UI state from diverging from the unkillable server-side operation.
Additional information
Minimum fix: in commands-compact.ts, construct an AbortController, pass its signal via the already-defined abortSignal field on CompactEmbeddedPiSessionParams, and register the compaction into ACTIVE_EMBEDDED_RUNS via setActiveEmbeddedRun(sessionId, handle, sessionKey) so that existing cancel primitives (chat.abort, abortEmbeddedPiRun) find it. The bulk of the type and inner-session plumbing is already in place.
Downstream workaround: UI clients can disable the cancel button while a /compact is in flight, so the user is not misled into expecting cancel to work. The CoClaw UI currently does this via a cancelDisabled prop on its chat input component.
Verified against OpenClaw commit d7cc6f7643 (v2026.4.14-beta.1+69).
Reported by the CoClaw team.
This issue was discovered while developing @coclaw/openclaw-coclaw, a CoClaw channel plugin for OpenClaw.
Bug type
Behavior bug (incorrect output/state without crash)
Beta release blocker
No
Summary
/compactinvokesruntime.compactEmbeddedPiSession(...)without passing anyabortSignaland without registering the compaction session intoACTIVE_EMBEDDED_RUNS. As a result neitherchat.abort,abortEmbeddedPiRun(sessionId), nor/stophas any effect on an in-progress/compact; the user has no way to cancel untilcompactionTimeoutMsexpires.Steps to reproduce
/compactto take tens of seconds or longer./compact.chat.abort,abortEmbeddedPiRun(sessionId)(directly or via theglobalThis[Symbol.for("openclaw.embeddedRunState")].activeRuns.get(sessionId).abort()side door), or/stop.Expected behavior
Invoking any supported cancel path should interrupt the compaction within a few seconds, consistent with any other embedded agent run. The compaction session should also appear in
ACTIVE_EMBEDDED_RUNSfor the duration, so external observers can discover it.Actual behavior
All cancel attempts are no-ops.
abortEmbeddedPiRun(sessionId)returnsfalseimmediately because the compaction session was never registered.chat.abortsimilarly finds nothing inchatAbortControllers. The compaction only ends when it completes successfully or whencompactionTimeoutMsfires.OpenClaw version
2026.4.12
Operating system
Ubuntu 22.04.5 LTS on WSL2 (Linux 6.6.87.2-microsoft-standard-WSL2)
Install method
npm global
Model
N/A (compaction uses whatever model the session is configured with; the cancel bug is independent of model selection)
Provider / routing chain
N/A (cancel path is orthogonal to provider routing)
Additional provider/model setup details
N/A
Logs, screenshots, and evidence
src/auto-reply/reply/commands-compact.ts(the current/compacthandler, approximately L72-145): the handler first invokesabortEmbeddedPiRun(sessionId) + waitForEmbeddedPiRunEnd(sessionId, 15_000)to stop the current run, then callsruntime.compactEmbeddedPiSession({...})without anabortSignalargument and without callingsetActiveEmbeddedRunfor the compaction itself.The type definition in
src/agents/pi-embedded-runner/compact.types.ts:56already declares:on
CompactEmbeddedPiSessionParams, so the parameter surface is prepared; the command path is simply not wiring it up.src/agents/pi-embedded-runner/compact.ts:520(prepareCompactionSessionAgent) already passes an internalrunAbortController.signalto a sub-session, so the inner mechanics exist.Impact and severity
/compacton a long-running or complex session./compactthat the user wants to abandon — for example when they realize they sent the command prematurely, or when compaction is visibly stuck.Additional information
Minimum fix: in
commands-compact.ts, construct anAbortController, pass itssignalvia the already-definedabortSignalfield onCompactEmbeddedPiSessionParams, and register the compaction intoACTIVE_EMBEDDED_RUNSviasetActiveEmbeddedRun(sessionId, handle, sessionKey)so that existing cancel primitives (chat.abort,abortEmbeddedPiRun) find it. The bulk of the type and inner-session plumbing is already in place.Downstream workaround: UI clients can disable the cancel button while a
/compactis in flight, so the user is not misled into expecting cancel to work. The CoClaw UI currently does this via acancelDisabledprop on its chat input component.Verified against OpenClaw commit
d7cc6f7643(v2026.4.14-beta.1+69).Reported by the CoClaw team.
This issue was discovered while developing @coclaw/openclaw-coclaw, a CoClaw channel plugin for OpenClaw.