Skip to content

fix: bump modal to >=1.4.3 for Function.with_options() - #791

Merged
ColeMurray merged 1 commit into
mainfrom
fix/modal-with-options-version
Jun 20, 2026
Merged

fix: bump modal to >=1.4.3 for Function.with_options()#791
ColeMurray merged 1 commit into
mainfrom
fix/modal-with-options-version

Conversation

@ColeMurray

@ColeMurray ColeMurray commented Jun 20, 2026

Copy link
Copy Markdown
Owner

Summary

The repo-image build endpoint crashes at runtime with:

Modal API error: 'Function' object has no attribute 'with_options'

packages/modal-infra/src/web_api.py:595 (the configurable build-timeout feature) calls:

await build_repo_image.with_options(timeout=function_timeout).spawn.aio(...)

Root cause

Function.with_options() was added in Modal 1.4.3. In 1.3.1–1.4.2 with_options
existed only on Cls (@app.cls()), never on Function (@app.function()).

uv.lock pinned modal 1.3.1, and CI deploys with uv sync --frozen
(terraform/modules/modal-app/scripts/deploy.sh), so production ran 1.3.1 and the
attribute 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 bumped modal>=0.73.0modal>=1.4.3
  • uv.lock: modal 1.3.1 → 1.4.3, pinned to exactly 1.4.3 (the minimum that has
    Function.with_options; not the latest 1.5.0, to keep the blast radius minimal)

Transitive changes from Modal 1.4.3: synchronicity 0.11.1→0.12.5, starlette bump;
Modal 1.4.3 dropped its typer/shellingham CLI deps, so uv removed them. The modal
CLI still works (modal client version: 1.4.3), so deploy.sh's uv run modal deploy
is unaffected.

Verification

  • uv sync --frozen (mirrors deploy.sh) installs Modal 1.4.3 with a working
    Function.with_options(timeout=...).
  • Unmocked check: the real build_repo_image.with_options(timeout=4200).spawn.aio
    chain now resolves against Modal 1.4.3 — no AttributeError.
  • Full modal-infra suite: 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. No CACHE_BUSTER
bump needed (that only affects sandbox image layers, not client injection).

Summary by CodeRabbit

  • Chores
    • Updated modal library dependency to version 1.4.3 or higher for enhanced compatibility.

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).
@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c40140b8-dc9a-4301-ad6c-7b16e387574f

📥 Commits

Reviewing files that changed from the base of the PR and between a4aceb3 and 9b290f8.

⛔ Files ignored due to path filters (1)
  • packages/modal-infra/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (1)
  • packages/modal-infra/pyproject.toml

📝 Walkthrough

Walkthrough

The modal package minimum version in packages/modal-infra/pyproject.toml is bumped from >=0.73.0 to >=1.4.3, with an inline comment noting that Function.with_options() requires this version.

Changes

modal Dependency Version Bump

Layer / File(s) Summary
modal minimum version update
packages/modal-infra/pyproject.toml
Raises the modal dependency floor from >=0.73.0 to >=1.4.3, adding an inline comment that Function.with_options() requires >=1.4.3.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Poem

🐇 A version number hops up the hill,
From zero-point-seventy-three, a tiny thrill,
Now one-point-four-point-three is the floor,
with_options() needs it — no less, no more,
The rabbit bumps deps and calls it a day! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: bumping the modal dependency to version >=1.4.3 to support the Function.with_options() method.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/modal-with-options-version

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown

Terraform Validation Results

Step Status
Format
Init
Validate

Note: Terraform plan was skipped because secrets are not configured. This is expected for external contributors. See docs/GETTING_STARTED.md for setup instructions.

Pushed by: @ColeMurray, Action: pull_request

@open-inspect open-inspect Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 updating packages/modal-infra/uv.lock directly 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.

@open-inspect open-inspect Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

@ColeMurray
ColeMurray merged commit e5c27a2 into main Jun 20, 2026
18 checks passed
@ColeMurray
ColeMurray deleted the fix/modal-with-options-version branch June 20, 2026 00:18
ColeMurray added a commit that referenced this pull request Jun 20, 2026
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.
ColeMurray added a commit that referenced this pull request Jun 20, 2026
## 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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant