mirror of
https://github.com/open-webui/computer.git
synced 2026-11-05 01:17:24 +00:00
[GH-ISSUE #209] bug: task silently marked complete when the post-compaction completion returns zero tokens #121
Labels
No labels
enhancement
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
open-webui/computer#121
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @ThalynLabs on GitHub (Aug 1, 2026).
Original GitHub issue: https://github.com/open-webui/computer/issues/209
Summary
An agent task ends mid-work and is recorded as successfully finished whenever the completion
request issued immediately after context compaction comes back
200 OKwith zero generated tokens.No error is raised, no retry is attempted, and the chat shows a normal completed assistant message
that stops mid-sentence. The user has to type "continue" to resume, at which point the run proceeds
normally.
Environment
0.9.19, installed viauvx, runningcptr run --headlessapi_type: chat_completions,provider_type: default)pointed at a local Ollama daemon, serving a cloud-hosted model (
glm-5.2, 1,000,000-tokenadvertised context)
CHAT_COMPACT_TOKEN_THRESHOLD(80,000), unset in the environmentWhat happens
Every observed stop follows the same five-step trace, with no other pattern in between:
The 158 ms round trip is the tell, and the session-wide latency distribution is cleanly bimodal.
Across 43 completion requests to this model, exactly five took under 0.5 s — 81, 99, 127, 130 and
158 ms — and those five are precisely the five stops. Every other request in the session took
between 0.6 s and 63.4 s. Nothing was generated in the fast five.
That is confirmed in the database rather than inferred from timing. The persisted assistant message
carries the usage reported by that final response:
last_usageis reset toNoneat compaction (utils/chat_task.py, in the compaction block), sothis all-zero usage object is what the post-compaction response itself reported. The response
consisted of a zero usage event and a
doneevent, and nothing else.The stored
contentis whatever the task had accumulated before compaction, and in every case itends at the moment the model was about to act:
"...Now let me set up my task tracking and begin the actual verification work.""...Now let me read the remaining reference documents.""...I'll use run_command with ripgrep instead.""...starting with recording the git state and running the mechanical checks."Frequency
In one 100-minute session on this model: 10 compaction events across 6 tasks.
99 ms, 130 ms, 158 ms, and 127 ms.
times and only stopped on the third. So the empty completion is intermittent, but it only ever
appeared in the post-compaction slot.
(
input_tokens: 22567, output_tokens: 370).Where the defect is
utils/chat_task.py, the stream event loop —elif event["type"] == "done":(line 2256 in 0.9.19).When the response carries no pending tool calls, the handler unconditionally flushes text, saves the
message with
done=True, pops task state, emitsCHAT_FINISHED, setstask_completed_success = True, and returns.There is no check that the iteration produced anything. An iteration that yielded zero text deltas,
zero output items, zero tool calls, and zero tokens is indistinguishable, at that branch, from a
model that finished its work.
An empty completion is not a completion. The current behaviour converts a transient upstream
non-answer into a permanent, silent, successful-looking truncation of an agent run — the worst of the
available outcomes, because nothing surfaces to the user and the DB records success.
Suggested fix
At the
donebranch, before treating the task as complete, check whether this iteration produced anyoutput at all — text, output items, tool calls — and whether reported usage is non-zero. If it
produced nothing:
the failure is visible instead of silent.
Failing the task loudly would already be a large improvement over the current silent success, even
without the retry.
Open question — why is the post-compaction request empty?
This report is about cptr accepting the empty response, which is a defect regardless of cause. But
the trigger is worth investigating too, because the empty responses cluster in exactly one place. Two
candidates, not distinguished from outside:
compaction is a coincidence of load or timing. Unlikely given 5 for 5.
silence — e.g. the reshaped message list, or the summary-augmented system prompt, or the interaction
between the two.
Setting
CPTR_LOG_UPSTREAM_REQUESTS=trueand capturing the exact post-compaction request body wouldsettle this quickly; that log was not enabled when these traces were captured.
Workaround in use
Raising the compaction threshold for the affected model reduces how often the condition can fire, via
per-model config:
This is mitigation only. It lowers the frequency of the trigger; it does not stop cptr from accepting
an empty completion as a finished task.
Secondary observation (separate, lower priority)
Twice in the same session the summarizer failed and fell back:
Both fallbacks produced a truncated 2000-character summary where real summaries ran 2100–3900
characters — a measurably worse handoff into the compacted context. This is not the cause of the
stops: one of the two fallback compactions continued generating normally 56 seconds later. Noting
it only because a silent degradation of summary quality is hard to spot from the UI.