Repository navigation
Retry compose lifecycle commands on a panic, keep both ends of script output, bump compose to v5.5.1 - #40
Conversation
…ipt output A universe load onto a multi env dies when the docker compose binary itself crashes during the snapshot restore (`rm -sf -v` + `up -d`, or `up -d --force-recreate`): compose has data races that end in a Go runtime panic, exit code 2, and the step failed on the first one even though both commands are idempotent. exec_script grows an opt-in retry_exit_codes, and the two compose calls in _load_from_snapshot use it with (2,). The error raised by exec_script kept only the last 1500 chars of each stream, which for a Go crash is the end of the goroutine list and never the panic header. It now keeps the first and last 1500 chars around an elision marker. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The VM image installs Ubuntu 22.04's docker.io, now Docker Engine 29.x, next to a compose plugin from September 2024. Move to the current release so the engine and the plugin come from the same era. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The servicedb recreate merges stderr into stdout, so the retry warning showed an empty stderr for exactly the crash it exists to surface. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
| await self._sandbox.exec_script( | ||
| f"cd {GATEWAY_APP_DIR} && docker compose rm -sf -v {DATABASE_SERVICE_NAME} && docker compose up -d {DATABASE_SERVICE_NAME} 2>&1" | ||
| f"cd {GATEWAY_APP_DIR} && docker compose rm -sf -v {DATABASE_SERVICE_NAME} && docker compose up -d {DATABASE_SERVICE_NAME} 2>&1", | ||
| max_retries=2, retry_exit_codes=(2,), |
There was a problem hiding this comment.
Both snapshot commands hardcode max_retries=2, and the retry log in sandbox.py uses an inline 200-character limit. The repository requires magic numbers to be stored as descriptively named class or instance variables. Name these limits before merging so their purpose is clear and the two commands stay in sync.
Rule Used: Store magic numbers as class or instance variables with descriptive names rather than using them inline in the code. (source)
Learned From
scaleapi/scaleapi#126388
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agent_env/env/envs/multi_env.py
Line: 599
Comment:
**Retry counts lack names**
Both snapshot commands hardcode `max_retries=2`, and the retry log in `sandbox.py` uses an inline `200`-character limit. The repository requires magic numbers to be stored as descriptively named class or instance variables. Name these limits before merging so their purpose is clear and the two commands stay in sync.
**Rule Used:** Store magic numbers as class or instance variables with descriptive names rather than using them inline in the code. ([source](https://app.greptile.com/scale-ai/-/custom-context?memory=002e0051-41ad-46c1-9098-47433c580150))
**Learned From**
[scaleapi/scaleapi#126388](https://github.com/scaleapi/scaleapi/pull/126388)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Fixed in bbf6386: the two compose calls now share _COMPOSE_CRASH_RETRIES / _COMPOSE_CRASH_EXIT_CODES (module constants in multi_env.py), and the retry log uses _RETRY_LOG_CLIP_CHARS next to _OUTPUT_CLIP_CHARS in sandbox.py.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Live verificationBranch installed editable; env
¹ run A's harness listed tools with a wrong filter and counted 0; fixed before B and the regression run. ² includes a ~90 s Mongo write timeout on the instance record from my machine, unrelated to the change. Both chaos runs show the new warning with the panic header preserved: Inside every VM: Unit suite: 5768 passed. Greptile: one P2 (unnamed constants), fixed in bbf6386. |
Why
load_artifactof a universe onto amultienv onmodal_vmintermittently fails withScript failed (exit 2)and the tail of a Go goroutine dump, raised fromMultiEnv._load_from_snapshotatdocker compose up -d --force-recreate …(one dump also shows thedocker compose rm -sf -v servicedb && up -d servicedbpath). Exit 2 is Go's unrecovered-panic exit; the binary is compose v2.29.7, and the panic family is compose's known data races duringup --force-recreate/ stop (docker/compose#10319, #10468, #12335, #12787, #12834). Six first attempts on one env hit it between 2026-09-30 and 2026-10-01; the activity-level retry hid all of them except a run started in-process, where the first crash was fatal. Diagnosis was blocked byexec_scriptkeeping only the last 1500 chars of stderr, which for a Go crash never includes thepanic:line.What
VmSandbox.exec_scriptgainsretry_exit_codes;_load_from_snapshotpassesmax_retries=2, retry_exit_codes=(2,)on its two compose lifecycle commands, both idempotent. Thepg_isreadyprobe keeps its own loop and is untouched (pg_isreadyitself exits 2 for "no response").exec_scriptnow carries the first and last 1500 chars of stdout and stderr around an elision marker (clip_output), so the next crash is attributable._COMPOSE_VERSIONv2.29.7 → v5.5.1, as a separate commit. The VM image'sdocker.iois Docker Engine 29.1.3 today; the plugin was from September 2024.Verification
tst/unit: 5768 passed, 7 new (retry only on listed codes, fail fast otherwise, give up aftermax_retries, panic header and tail both survive, clipping exact).docker-composeplugin with a shim that prints a fake goroutine dump and exits 2 on its firstup -d --force-recreateand execs the real binary afterwards, load the universe; expect one logged retry and a clean load. Then a plain deploy + load for regression on the new compose. Results in a comment below.Linear: FD-3360
🤖 Generated with Claude Code
The PR should meet the repository’s variable-placement rule before merging.
Fix with agent prompt
Summary
Multi-environment snapshot restores retry Compose exit code 2, and script errors keep both ends of long output. Modal VM images also move to Compose v5.5.1.
Reviews (2) · Last reviewed commit: "Name the compose crash retry budget and ..."