Repository navigation
[Bug]: Session remains permanently stuck after temporary provider failure during /goal #425
Description
Product or interface
CLI - interactive TUI
Version
0.6.2
Platform
Linux
OS version and architecture
Ubuntu 24.04.5 LTS x64
Issue area
Agent stuck / slow / repeated loop
Desktop log upload ID (optional)
N/A - CLI
Steps to reproduce
Observed sequence (not yet confirmed as deterministic):
- Start a session with /goal active and running autonomous turns.
- While /goal is running, the BYOK provider temporarily becomes unavailable.
- MCode reports provider error 50113.
- The provider later recovers; other/new MCode sessions work normally.
- The affected session does not recover:
- /goal remains stuck/Loading
- normal messages such as "hi" or "continue" do not execute
- /retry does not recover it
- /goal clear does not recover ordinary chat
- The only workaround is abandoning the affected session and opening a new one.
Expected and actual behavior
EXPECTED
provider temporarily fails during /goal
↓
current turn fails/retries/pauses safely
↓
provider comes back
↓
session accepts turns normally again
ACTUAL
provider temporarily fails during /goal
↓
error 50113
↓
provider comes back
↓
affected session remains stuck
↓
/goal cannot continue
↓
ordinary chat also cannot execute
↓
/goal clear does not recover session
↓
must create a new session
===
Technical note for maintainers:
Inspection suggests a possible ACP session recovery/cleanup issue.
- Failed/aborted ACP interactions can remain detached/pending.
- The runtime has a 32-interaction limit; exhaustion can close the ACP connection.
- This would explain why ordinary turns also stop working after the provider recovers.
- /retry uses the same affected session/connection.
- /goal clear clears Goal state but does not appear to reset the underlying ACP connection.
- New sessions work normally.
Suspected area: ACP interaction cleanup / session connection recovery after provider failure.
This is a suspected root cause from runtime inspection, not a confirmed diagnosis.
Redacted error summary
Error: The model provider is temporarily unavailable.
Code: 50113
Run /retry to resend your last message. Your prompt is preserved.
After the provider recovered, other/new MCode sessions worked normally,
but this specific session remained unusable.
Normal turns did not execute, /retry did not recover it, and /goal clear
did not restore the session.Screenshots
- 50113 error after temporary provider outage during /goal.
- Affected session stuck after provider recovery.
- Repeated normal messages ("continue", "hi") not executing.
Sensitive paths/project information redacted where applicable.
Before submitting
- I have searched existing issues.
- I have included my version and removed sensitive information.
Activity
hetaoBackend commentedon Oct 4, 2026
@TheBaby5 — thanks for the structured repro and, importantly, for being explicit that the ACP root cause is a suspected diagnosis from inspection rather than a confirmed one. That framing makes this triageable. I verified the concrete mechanism you suspected, and it checks out.
Verification (against
main)The limits you inferred are real and literally named in the ACP agent:
packages/tui/src/acp/agent.ts:48-49—MAX_DETACHED_LIFECYCLES_PER_SESSION = 2andMAX_DETACHED_LIFECYCLES_TOTAL = 32.:50-51—MAX_ADMITTED_LIFECYCLES_PER_SESSION = 64/MAX_ADMITTED_LIFECYCLES_TOTAL = 256.So the "32-interaction limit" you suspected does exist, and there is a real detached-lifecycle accounting path (
detachedGenerations,detachedGenerationCount, gated at:1868-1869and:1891-1892). Your hypothesis — that failed/aborted ACP interactions can stay detached/pending and eventually starve the session — is grounded in the actual control flow, not invented. Also consistent with your observation that new sessions work fine while the affected one doesn't: the exhaustion is per-connection/per-session state, not global.Assessment
bug(as filed) — a session that can never recover after a transient provider failure is a serious usability failure: the user is forced to abandon the session entirely, and (worse) any in-flight work state tied to it./goal clearcan't run. That "provider is fine, but this session is bricked" split is the key symptom to fix.Classification
needs-triage— plausible, partially-verified root cause; needs a maintainer with runtime access to reproduce and confirm (or refute) the detached-exhaustion theory. (This tracker has noready-for-humanlabel, soneeds-triage+ this note is the routing.)What would help most
MAX_DETACHED_LIFECYCLES_TOTAL(32) or the per-session cap (2) — if you can tell which, that pins the mechanism./goalis necessary to trigger it, or whether a plain turn that fails mid-stream during a provider outage can brick a session the same way. That determines whether this is Goal-specific or a general session-recovery bug.Your instinct to point at ACP interaction cleanup — and to explicitly note it's suspected, not confirmed — is exactly the right level of rigor. Happy to re-triage with a confirmed repro if you can capture one.
No credentials or sensitive data echoed; the ACP session-cap reasoning is from source, which is public here.
TheBaby5 commentedon Oct 4, 2026
Thanks — I still had the affected old session, so I inspected its preserved runtime/SQLite state read-only to answer the two questions you asked.
1. Was it the per-session cap (2) or total cap (32)?
I cannot prove which cap was hit.
The detached-lifecycle counters appear to be in-memory only; I could not find historical values persisted in SQLite, the session ledger, or durable logs. So after the fact there is no reliable way to reconstruct whether this hit:
MAX_DETACHED_LIFECYCLES_PER_SESSION = 2MAX_DETACHED_LIFECYCLES_TOTAL = 32I do not want to claim either one without evidence.
What is preserved is the failure boundary: after the bad turn, subsequent ordinary turns were accepted into
turn_ingressbut endedaborted/failedwithout reaching an LLM or tool call.So the session remained stuck below the Goal layer even though other/new sessions worked normally.
2. Is
/goalrequired?The evidence suggests this may be a general session-recovery bug rather than Goal-specific, but I cannot claim a live non-Goal reproduction yet.
Source-level:
Preserved-session evidence:
/goal cleardid not restore them;local_runtime_thread_goalswas empty when inspected;mavis-internal:goal:*turns remained inturn_ingress.One important correction from my original report: the durable session record shows the triggering provider-side failure as:
MCode surfaced the session-level error as
50113.So I can no longer prove from the preserved state that the original trigger was specifically a provider outage during
/goal.What I can prove is:
That makes the more useful bug boundary look like ACP/session admission recovery after a failed provider turn, with
/goalpotentially only being how I originally encountered it.I still have the preserved affected session and can inspect further if you want a specific state/log/source path checked.
hetaoBackend commentedon Oct 4, 2026
Thanks for the report. We tried to reproduce this with the interactive TUI against a provider failing with 5xx, connection resets and mid-stream cuts, and in each case the session recovered once the provider came back (
hi,/retryand/goal resumeall worked). The only stuck state we could produce was a request that never got a response, which #428 now bounds.To narrow down your case, could you share:
mcode acp(e.g. an editor/IDE integration), or the interactive terminal UI?fix: keep prior first-response wait and stop reading abandoned streams (
fix(agent-core): bound hung model requests with first-event and idle …
TheBaby5 commentedon Oct 4, 2026
For clarity: the old affected session remains stuck/retrying with
50113...while a new session using the exact same API key + provider works normally at the same time — so the provider/key is healthy and the failure is isolated to that session.
TheBaby5 commentedon Oct 4, 2026
One extra concrete data point from the exported affected session:
So the
31 > 30 imagesrejection is consistent with cumulative image history being resent with later turns, not with the provider/key being unhealthy. :chatgpt-content-reference{index="0"} :chatgpt-content-reference{index="1"}A regression test that would directly cover my case:
merge upstream 56221c1 (MiniMax-AI#429 rebuild différé après shrink, M…
fix(images): parse attachment reminder paths with a linear scan
hetaoBackend commentedon Oct 5, 2026
Hi @TheBaby5, thanks a lot for the detailed report and the regression-test idea. It made this easy to pin down.
We reproduced it locally: pasted images stay in the session history, and every request re-sends the whole history, so once a session holds more than 30 images every later request (even plain text,
/retry,/compact, or a restarted session) getsToo many images in request: 31 > 30. Each failure was also retried several times behind a generic "temporarily unavailable" message.Draft PR #431 addresses this: requests now carry only the most recent images (20 by default, configurable per model with
max_images_per_request), with older ones replaced by a short note naming the file; this rejection now fails once with the provider's reason and a/compactor/newhint; and/compactfalls back to an image-free summary so a stuck session can recover.Two quick questions that would help us confirm it covers your setup: which provider/gateway (and model) were you using, and were the images mostly pasted screenshots or produced by tools (e.g. browser screenshots)? If you're able to try the branch, feedback is very welcome.
fix(agent-core): cap images per request and recover sessions over the…
TheBaby5 commentedon Oct 5, 2026
Thanks — I tested #431 against copies of my actual preserved affected sessions, using the same real provider/gateway/model. The fix works.
Provider / gateway / model
custom_provider:opencode-gohttps://opencode.ai/zen/go/v1deepseek-v4.1-flashopenai-completionsThis is recorded in the affected sessions'
llm-call.jsonand also appears in the original BYOK error itself.Image source
The images were mostly tool-generated, not pasted by me.
So roughly 77–79% were tool-generated. They came from the
readtool reading image files, not browser-screenshot tool output directly.One correction to my earlier comment: the authoritative provider-visible image counts in the preserved sessions are 31 and 34, not 44. The provider's own errors (
31 > 30,34 > 30) match those stored inline-image counts exactly.Real #431 validation
I built merge commit
1852771in an isolated temporary checkout and tested it against copies of both broken sessions, with the same real OpenCode Zen gateway + DeepSeek V4.1 Flash.The stored histories remained unchanged; only the outbound request copy was capped. I also verified the original session files were byte-identical by SHA-256 before and after testing.
The effective
max_images_per_requeston my setup is the default 20, which is safely below this gateway's observed limit of 30.I also verified the error-classification change against the real preserved error string: it is now recognized as a deterministic
image_limitrejection, so the pointless retry loop is suppressed, while normal transient errors such as 503, 429, and ECONNRESET remain retryable.I couldn't drive a live TUI
/compactheadlessly, but the mergedcompactContext provider image-limit recovery (#425)tests all pass, including the image-free fallback path.One practical note: my installed MCode was still 0.6.1, which does not contain this fix. The isolated 0.6.2 build does.
So from my side: #431 fixes the real issue on both affected sessions.
hetaoBackend commentedon Oct 6, 2026
Hi @TheBaby5, thank you for testing #431 against copies of both of your real stuck sessions, on the same gateway and model, and for checking that the original session files were left untouched. That was exactly the confirmation we needed.
To sum up for anyone who finds this later: the stuck session came from image history being re-sent on every request. Once a session held more than 30 images, each request got
Too many images in request: 31 > 30, retried several times behind a generic error. #431 (merged as 1852771) now sends only the most recent images (20 by default, configurable per model withmax_images_per_request) and replaces older ones with a short placeholder. It fails this rejection once with the provider's reason and a/compactor/newhint, and/compactfalls back to an image-free summary. Separately, #428 bounds requests that never get a response.The fix will ship in the next release; the 0.6.1 you have installed doesn't include it. I'm closing this as fixed. If a session gets stuck again after upgrading, please reopen or file a new issue with the error text and we'll take another look.
merge: upstream a5b56b7 (MiniMax-AI#444 system prompt, MiniMax-AI#443 …