P4: the worker advertises lease slots its memory budget can no longer admit, so turns get an in-turn tool error instead of a 503
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- go, typescript
- Domain
- backend, infrastructure
Research direction
Start with remote-worker/internal/vmpool/errors.go and microvm-worker/main.go to trace how memory-budget refusals and worker capacity are handled; then inspect the harness path that turns exec status into an HTTP response. The issue identifies mapping budget refusals to saturation as the smallest user-visible fix. Done means a refusal produces a 503 with Retry-After instead of an in-turn tool error.
Written by the indexing model from the issue text.
Description
Found during the P6.3 acceptance (#425, Task 18 step 1) on the shared KVM rig.
What happened
A P6 host ran container sandboxes plus one P4 microvm-worker (moca_microvm_0), with MICROVM_MAX_COMMITTED_MB=8192. With the unit's 4 GiB SH_MEMORY_RESERVE_MB, that leaves a 4 GiB VM budget, about 14 VMs at 288 MiB each. SH_WORKSPACE_IDLE=8h and SH_STANDBY_DEPTH=2.
After about 12 P4 sessions, every turn of the next three sessions failed. Each exec came back as a tool error:
memory-budget: committing 301989888 more bytes would reach 4529848320 against a budget of 4294967296
(MaxCommittedBytes 8589934592 less MemoryReserveBytes 4294967296)
The model received that as the bash tool's output. The turns did not get a 503 with Retry-After. The sessions stayed in their tier, which is correct per P6.3.
Why
- The worker's presence record advertises
capacityMax=WORKER_MAX_CONCURRENT(16): concurrent exec slots. - The supervisor's lease cap uses that number.
remote-worker/internal/vmpool/errors.gocalls it "primary admission control", withMaxRunsand the memory budget as backstops. The wire contract has no "busy" frame, so a backstop refusal can only surface as an exec error. - The boot-time budget check (
microvm-worker/main.go, around L128) sizes the budget formaxConcurrent × (1 + StandbyDepth)VMs. - A session's idle, resident workspace VM holds memory for
SH_WORKSPACE_IDLE(8 h here), yet it uses no lease slot. So the memory a worker has committed grows with the number of distinct recent sessions, not with concurrency. The worker keeps advertising free slots it can no longer admit. - P6.3's affinity keeps each session on its sandbox, so all of a session's turns reuse its resident VM. That is right for the workspace, but it means a busy P4 host reaches this state sooner.
What a user sees
New P4 sessions fail with a tool error in the transcript, on a host that reports spare capacity. Nothing retries, and nothing says "at capacity".
Options
- Report the real headroom. The worker lowers its effective capacity, or marks itself saturated, when the memory budget cannot admit one more VM. That needs a presence update;
Hellois sent once, so this needs either a capacity update frame or a re-Hello. - Make a refusal retryable. Map a budget refusal (
RefuseMemoryBudget, ormax-runs) to an exec status the harness classifies as saturated, so the turn answers 503 withRetry-Afterinstead of handing the error text to the model. - Evict under pressure. Reclaim the least-recently-used idle workspace VM (it is persisted on disk under
SH_WORKSPACE_ROOT) before refusing. - Document it. In
P4-ON-P6.md, sizeMICROVM_MAX_COMMITTED_MBandSH_WORKSPACE_IDLEfor the expected number of distinct sessions, not for concurrency.
(2) is the smallest user-visible fix. (3) stops a host's capacity from leaking away over time.
Repro
On a host with a small budget, create more distinct P4 sessions than the budget holds VMs, all within SH_WORKSPACE_IDLE. On the rig, the session after about 14 committed VMs failed. Raising the budget to 12288 MB let three more sessions pass.
- Dominant language
- TypeScript
- Stars
- 4
- Forks
- 9
- Avg merge
- 9h 31m
- Merged PRs (30d)
- 139
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from rossoctl/moca
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 1 day
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
rossoctl/moca#421 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 1 day
Similar issues
-
area: image-engine bug priority: low
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
snapotter-hq/SnapOtter#3885 ·
Maintainers usually reply within 1 day
-
Mend: dependency security vulnerability
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 3 days
-
pending triage
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
bug P3 UI/UX
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster no-stale P3
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
openclaw/openclaw#182077 · 1 comment · 1 reaction ·
Maintainers usually reply within 1 day