fix: bump modal to >=1.4.3 for Function.with_options() - #791
Conversation
web_api.py calls build_repo_image.with_options(timeout=...), but Function.with_options() was only added in Modal 1.4.3 (it existed solely on Cls in 1.3.1-1.4.2). uv.lock pinned modal 1.3.1 and CI deploys via uv sync --frozen, so the build-image endpoint raised at runtime: 'Function' object has no attribute 'with_options'. Bump the dependency floor to >=1.4.3 and regenerate uv.lock pinned to 1.4.3. Full modal-infra suite passes (152).
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe Changesmodal Dependency Version Bump
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~2 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Terraform Validation Results
Pushed by: @ColeMurray, Action: |
There was a problem hiding this comment.
Summary
PR #791 (fix: bump modal to >=1.4.3 for Function.with_options()) by @ColeMurray updates the Modal dependency floor and lockfile so the existing build_repo_image.with_options(...).spawn.aio(...) call is available at runtime. Reviewed 2 changed files, with 8 additions and 33 deletions.
Critical Issues
None found.
Suggestions
None.
Nitpicks
None.
Positive Feedback
- The fix is narrowly scoped to the dependency that provides the missing API and the corresponding lockfile changes.
- The deployment path uses
uv sync --frozen, so updatingpackages/modal-infra/uv.lockdirectly addresses the production failure mode. - I verified Modal 1.4.3 exposes
Function.with_options()in an unmocked compatibility check.
Questions
None.
Verdict
Approve: ready to merge.
There was a problem hiding this comment.
[deep review] No maintainability findings. This is the right shape for the fix: the version-dependent API requirement is captured at the package boundary, and the lockfile is updated without adding runtime compatibility branches or bespoke fallback logic.
modal_source_hash hashed only *.py/*.js/*.ts under src/, excluding packages/modal-infra/pyproject.toml and uv.lock. Since the data plane deploys via 'uv sync --frozen', the lockfile is a deploy input, so a dependency-only change (e.g. #791's modal>=1.4.3 bump) left source_hash unchanged and modal_deploy was a no-op — Modal was never redeployed. Add both files to the hash so dependency-only changes trigger a redeploy.
## Summary
The Terraform Modal deploy only redeploys when its `source_hash`
changes, but that hash was computed from **only `*.py/*.js/*.ts` under
`packages/{modal-infra,sandbox-runtime}/src`** — it excluded
`packages/modal-infra/pyproject.toml` and `uv.lock`.
The data plane deploys via `uv sync --frozen` (installs exactly the
lockfile), so the lockfile *is* a deploy input. Excluding it means a
**dependency-only change silently does not redeploy Modal**:
`null_resource.modal_deploy` (`terraform/modules/modal-app/main.tf`)
sees no trigger change and is a no-op. This is what swallowed #791's
`modal>=1.4.3` bump — the lockfile changed, but `modal deploy` never
ran, so the running container kept the old client.
## Fix
Include `pyproject.toml` + `uv.lock` in `modal_source_hash` (both the
Linux `sha256sum` and macOS `shasum` branches), so dependency-only
changes trigger a redeploy.
## Verification
- `terraform fmt -check` clean; `terraform validate` → "Success! The
configuration is valid."
- Confirmed the digest changes when only `uv.lock`/`pyproject.toml`
change (and stays a valid 64-char hash).
Summary
The repo-image build endpoint crashes at runtime with:
packages/modal-infra/src/web_api.py:595(the configurable build-timeout feature) calls:Root cause
Function.with_options()was added in Modal 1.4.3. In 1.3.1–1.4.2with_optionsexisted only on
Cls(@app.cls()), never onFunction(@app.function()).uv.lockpinned modal 1.3.1, and CI deploys withuv sync --frozen(
terraform/modules/modal-app/scripts/deploy.sh), so production ran 1.3.1 and theattribute was missing. It passed locally because dev environments had 1.4.3, and the
endpoint unit test mocks
with_options, so neither path exercised the real 1.3.1 object.Fix
pyproject.toml: floor bumpedmodal>=0.73.0→modal>=1.4.3uv.lock:modal 1.3.1 → 1.4.3, pinned to exactly 1.4.3 (the minimum that hasFunction.with_options; not the latest 1.5.0, to keep the blast radius minimal)Transitive changes from Modal 1.4.3:
synchronicity0.11.1→0.12.5,starlettebump;Modal 1.4.3 dropped its
typer/shellinghamCLI deps, so uv removed them. ThemodalCLI still works (
modal client version: 1.4.3), sodeploy.sh'suv run modal deployis unaffected.
Verification
uv sync --frozen(mirrorsdeploy.sh) installs Modal 1.4.3 with a workingFunction.with_options(timeout=...).build_repo_image.with_options(timeout=4200).spawn.aiochain now resolves against Modal 1.4.3 — no
AttributeError.modal-infrasuite: 152 passed.At runtime Modal mounts the deploy-client version into the function container, so once CI
redeploys with the locked 1.4.3 client, the endpoint gets
with_options. NoCACHE_BUSTERbump needed (that only affects sandbox image layers, not client injection).
Summary by CodeRabbit