Repository navigation
fix(cua): harden /v1/predict profile handling on the Modal volume (stale-view EPERM + executor boto3) - #957
Open
mercurialsolo wants to merge 1 commit into
Open
mercurialsolo wants to merge 1 commit into
mercurialsolo wants to merge 1 commit into
Conversation
Two related reliability fixes for the profile/snapshot path that caused
intermittent 500s and degraded snapshotting on the holo3 executor.
1. Modal-volume stale-view mkdir EPERM (intermittent 500 on /v1/predict).
A long-lived container's /data mount can lag the backend: a tenant dir
another container committed under /data/tenants isn't visible yet, so
mkdir(parents=True, exist_ok=True) tries to *create* it and the backend
rejects the conflicting create with EPERM ("Operation not permitted").
exist_ok can't rescue it because is_dir() reads the same stale view.
Fix: paths._ensure_dir() catches the EPERM, calls vol.reload() to resync
the mount, and retries once. The Modal entrypoint registers vol.reload
via set_volume_reload_hook so every container (API + executors) recovers.
Off Modal (no hook) the original error re-raises — no masking.
2. boto3 + zstandard missing from the executor images. ProfileSnapshotter
.from_env runs in the executors, not just api_image, but executor_image,
claude_executor_image, and run_holo3's own inline image lacked the deps —
so snapshot save/restore degraded with "requires boto3" on every holo3
run and named reusable profiles (login reuse) silently didn't persist.
Added as trailing pip layers (keeps the heavy vllm/torch + llama.cpp
layers cached).
Tests: tests/test_paths_volume_reload_retry.py covers EPERM-recovery,
no-hook re-raise, persistent-error re-raise, and happy path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 4, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two related reliability fixes for the
/v1/predictprofile/snapshot path, both surfaced by the same investigation (intermittent 500s on the canary + degraded snapshotting on the holo3 executor):1. Modal-volume stale-view
mkdirEPERM → intermittentPOST /v1/predict -> 500A long-lived container's
/datamount can lag the backend: a tenant dir another container committed under/data/tenantsisn't visible in this container's cached view yet, somkdir(parents=True, exist_ok=True)tries to create it and the backend rejects the conflicting create withEPERM("Operation not permitted").exist_okcan't rescue it becauseis_dir()reads the same stale view.Fix:
paths._ensure_dir()catches theEPERM, callsvol.reload()to resync the mount, and retries once. The Modal entrypoint registersvol.reloadviaset_volume_reload_hook, so every container (API + executors) recovers. Off Modal (no hook) the original error re-raises — no masking.2.
boto3+zstandardmissing from the executor images → snapshot lifecycle degradedProfileSnapshotter.from_envruns in the executors, not justapi_image— butexecutor_image,claude_executor_image, andrun_holo3's own inline image lacked the deps. So snapshot save/restore failed withrequires boto3on every holo3 run, and named reusable profiles (login reuse) silently didn't persist. Added as trailing pip layers so the heavyvllm/torch+llama.cpplayers stay cached (perfeedback_modal_pip_layer_split).Tests
tests/test_paths_volume_reload_retry.py— 4 tests, all passing:mkdirsucceeds first tryVerification
4 passed).mantis-cua-server; snapshot capture now succeeds on the holo3 path (profile_snapshot capture ... outcome=captured size=266MB), and 3/3 real/v1/predictsubmits on fresh containers returned200with noEPERM.🤖 Generated with Claude Code