feat(sozo): warn instead of error on RPC spec version mismatch#3402
feat(sozo): warn instead of error on RPC spec version mismatch#3402
Conversation
When the node reports a starknet_specVersion that does not match the one sozo was built against, emit a warning via SozoUi and continue instead of aborting the command. A genuinely incompatible RPC will still surface the real failure at the call that actually breaks, with a much more specific error than the blanket version gate. Parse failures on the version string are also downgraded to a warning. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Ohayo sensei! 🌸 Walkthroughget_world_diff_and_provider no longer returns an error on Starknet RPC Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
bin/sozo/src/utils.rs (1)
123-136: Consider treatingspec_version()RPC failure the same way, sensei.Right now line 123 still uses
?, so if the node responds butstarknet_specVersionitself errors (e.g. method not exposed, transient RPC hiccup), sozo hard-fails before the new warn-and-continue path can help. Given the PR's stated goal — "let the actual incompatibility surface at the specific RPC call site" — it may be worth downgrading this to a warning too and proceeding with an unknown version assumption. Optional; happy to defer if the current scope is intentionally narrow.♻️ Sketch
- let spec_version = provider.spec_version().await?; - trace!(spec_version); - - match is_compatible_version(&spec_version, RPC_SPEC_VERSION) { - Ok(true) => {} - Ok(false) => ui.warn(format!( - "Starknet RPC version mismatch: node reports {spec_version}, sozo was built \ - against {RPC_SPEC_VERSION}. Continuing anyway; operations may fail if RPC \ - methods differ." - )), - Err(e) => ui.warn(format!( - "Could not parse Starknet RPC version '{spec_version}': {e}. Continuing." - )), + match provider.spec_version().await { + Ok(spec_version) => { + trace!(spec_version); + match is_compatible_version(&spec_version, RPC_SPEC_VERSION) { + Ok(true) => {} + Ok(false) => ui.warn(format!( + "Starknet RPC version mismatch: node reports {spec_version}, sozo \ + was built against {RPC_SPEC_VERSION}. Continuing anyway; operations \ + may fail if RPC methods differ." + )), + Err(e) => ui.warn(format!( + "Could not parse Starknet RPC version '{spec_version}': {e}. Continuing." + )), + } + } + Err(e) => ui.warn(format!( + "Could not query Starknet RPC spec version: {e}. Continuing." + )), }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@bin/sozo/src/utils.rs` around lines 123 - 136, The call to provider.spec_version() currently uses the ? operator and will hard-fail; change it to handle errors like the version-parse path: call provider.spec_version().await and match on Result, logging a ui.warn on Err (including the error) and set spec_version to a safe "unknown" or empty value so the subsequent is_compatible_version(&spec_version, RPC_SPEC_VERSION) check runs; update references to spec_version, provider.spec_version(), RPC_SPEC_VERSION, is_compatible_version, and ui.warn accordingly so failures to fetch the RPC spec are downgraded to warnings and execution continues.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@bin/sozo/src/utils.rs`:
- Around line 126-136: CI failed due to rustfmt formatting in the new match
block around is_compatible_version/spec_version/RPC_SPEC_VERSION that calls
ui.warn; run the formatter and commit the changes by running `cargo fmt -p sozo`
(or `rustfmt` on bin/sozo/src/utils.rs) locally, verify the match block and
surrounding lines are reflowed, then stage and push the formatted file so the
repository contains the rustfmt-compliant version.
---
Nitpick comments:
In `@bin/sozo/src/utils.rs`:
- Around line 123-136: The call to provider.spec_version() currently uses the ?
operator and will hard-fail; change it to handle errors like the version-parse
path: call provider.spec_version().await and match on Result, logging a ui.warn
on Err (including the error) and set spec_version to a safe "unknown" or empty
value so the subsequent is_compatible_version(&spec_version, RPC_SPEC_VERSION)
check runs; update references to spec_version, provider.spec_version(),
RPC_SPEC_VERSION, is_compatible_version, and ui.warn accordingly so failures to
fetch the RPC spec are downgraded to warnings and execution continues.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 53fe3d9a-9f4e-4154-80d0-e2499f69e10d
📒 Files selected for processing (1)
bin/sozo/src/utils.rs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extend the soften-on-version-stuff treatment to cover the case where the starknet_specVersion RPC call itself fails (method not exposed, transient network issue). Same rationale as the mismatch case: if the node is genuinely incompatible, the real error surfaces at the specific RPC call that breaks. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
bin/sozo/src/utils.rs (1)
123-142: Ohayo sensei — warn-and-continue reads well.The refactor cleanly covers all three paths (compatible, incompatible, parse/query failure) and matches the PR intent. Downstream RPC call sites will surface the real error if the node is truly incompatible, which is the right tradeoff over aborting every command on a version string mismatch.
One small nit you can take or leave: the three warn messages each end with a slightly different "Continuing..." tail ("Continuing anyway; ...", "Continuing.", "Continuing; ..."). Unifying the phrasing (e.g., always "Continuing; operations may fail if RPC methods differ.") would make the UX a touch more consistent, but it's purely cosmetic.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@bin/sozo/src/utils.rs` around lines 123 - 142, The three ui.warn messages in the match over provider.spec_version() use slightly different trailing phrasing; make them consistent by updating the messages emitted in the incompatible branch, the parse error branch, and the query error branch to use the same tail (for example: "Continuing; operations may fail if RPC methods differ."); locate the block around provider.spec_version().await and change the strings passed to ui.warn (in the is_compatible_version match's Ok(false) arm, the Err(e) parse arm, and the Err(e) provider.spec_version() arm) so they all end with the unified phrase while keeping the specific context text before it.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@bin/sozo/src/utils.rs`:
- Around line 123-142: The three ui.warn messages in the match over
provider.spec_version() use slightly different trailing phrasing; make them
consistent by updating the messages emitted in the incompatible branch, the
parse error branch, and the query error branch to use the same tail (for
example: "Continuing; operations may fail if RPC methods differ."); locate the
block around provider.spec_version().await and change the strings passed to
ui.warn (in the is_compatible_version match's Ok(false) arm, the Err(e) parse
arm, and the Err(e) provider.spec_version() arm) so they all end with the
unified phrase while keeping the specific context text before it.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d3352013-9b2c-4808-9055-cb16850d1151
📒 Files selected for processing (1)
bin/sozo/src/utils.rs
|
The dojo tests are failing and should be fixed by #3403 |
|
Claude finished @kariy's task —— View job Documentation Analysis CompleteTask: Review PR #3402 changes and update documentation in dojoengine/book if user-facing behavior changed. Todo list:
AnalysisChange Summary: Documentation Search Results:
Decision: No Documentation Updates NeededFollowing the documentation rules strictly:
Conclusion: No documentation updates required. The change improves internal error handling without introducing new user-facing features, workflows, or configuration requirements. |
Updates the pinned dojoengine/dojo revision used by dojo-integration-test from v1.7.0-alpha.2 to a6c6047d5e038b83041e06ecfb704ab390981140 so the integration test runs against the current tip of dojo's main branch, which includes dojoengine/dojo#3402. Also bumps scarb from dev-2025-09-05 to 2.13.1 to match the cairo/starknet 2.13 pins in examples/spawn-and-move/Scarb.toml, and switches the project build step from sozo build to scarb build. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Updates the pinned dojoengine/dojo revision used by dojo-integration-test from v1.7.0-alpha.2 to a6c6047d5e038b83041e06ecfb704ab390981140 so the integration test runs against the current tip of dojo's main branch, which includes dojoengine/dojo#3402. Also bumps scarb from dev-2025-09-05 to 2.13.1 to match the cairo/starknet 2.13 pins in examples/spawn-and-move/Scarb.toml, switches the project build step from sozo build to scarb build, and clones Dojo into /tmp/dojo instead of inside $GITHUB_WORKSPACE so proc-macro resolution during scarb build doesn't collide with Katana's root Cargo.toml workspace. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Updates the pinned dojoengine/dojo revision used by dojo-integration-test from v1.7.0-alpha.2 to a6c6047d5e038b83041e06ecfb704ab390981140 so the integration test runs against the current tip of dojo's main branch, which includes dojoengine/dojo#3402. Also bumps scarb from dev-2025-09-05 to 2.13.1 to match the cairo/starknet 2.13 pins in examples/spawn-and-move/Scarb.toml, switches the project build step from sozo build to scarb build, clones Dojo into /tmp/dojo instead of inside \$GITHUB_WORKSPACE so proc-macro resolution during scarb build doesn't collide with Katana's root Cargo.toml workspace, and builds sozo from the cloned Dojo source so migrate runs with the sozo matching the revision under test instead of a stale asdf-installed release. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Updates the pinned dojoengine/dojo revision used by dojo-integration-test from v1.7.0-alpha.2 to a6c6047d5e038b83041e06ecfb704ab390981140 so the integration test runs against the current tip of dojo's main branch, which includes dojoengine/dojo#3402. Also bumps scarb from dev-2025-09-05 to 2.13.1 to match the cairo/starknet 2.13 pins in examples/spawn-and-move/Scarb.toml, switches the project build step from sozo build to scarb build, clones Dojo into /tmp/dojo instead of inside \$GITHUB_WORKSPACE so proc-macro resolution during scarb build doesn't collide with Katana's root Cargo.toml workspace, builds sozo from the cloned Dojo source so migrate runs with the sozo matching the revision under test instead of a stale asdf-installed release, and starts Katana with --dev --dev.no-fee so sozo migrate transactions aren't rejected by the mempool's minimum L1 gas price check. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Updates the pinned dojoengine/dojo revision used by dojo-integration-test from v1.7.0-alpha.2 to a6c6047d5e038b83041e06ecfb704ab390981140 so the integration test runs against the current tip of dojo's main branch, which includes dojoengine/dojo#3402. Also bumps scarb from dev-2025-09-05 to 2.13.1 to match the cairo/starknet 2.13 pins in examples/spawn-and-move/Scarb.toml, switches the project build step from sozo build to scarb build, clones Dojo into /tmp/dojo instead of inside \$GITHUB_WORKSPACE so proc-macro resolution during scarb build doesn't collide with Katana's root Cargo.toml workspace, builds sozo from the cloned Dojo source so migrate runs with the sozo matching the revision under test instead of a stale asdf-installed release, and starts Katana with --dev --dev.no-fee so sozo migrate transactions aren't rejected by the mempool. The no-fee flag is needed because Katana's genesis block header is initialized with GasPrices::MIN (1 wei) while the live gas oracle used by mempool validation returns 20 gwei, and sozo (via starknet-rs) estimates fees against BlockTag::Latest which points to genesis right after startup, so the estimated max L1 gas price ends up at 1 wei and gets rejected against the oracle's 20 gwei floor. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Updates the pinned dojoengine/dojo revision used by dojo-integration-test from v1.7.0-alpha.2 to a6c6047d5e038b83041e06ecfb704ab390981140 so the integration test runs against the current tip of dojo's main branch, which includes dojoengine/dojo#3402. Also bumps scarb from dev-2025-09-05 to 2.13.1 to match the cairo/starknet 2.13 pins in examples/spawn-and-move/Scarb.toml, switches the project build step from sozo build to scarb build, clones Dojo into /tmp/dojo instead of inside $GITHUB_WORKSPACE so proc-macro resolution during scarb build doesn't collide with Katana's root Cargo.toml workspace, builds sozo from the cloned Dojo source so migrate runs with the sozo matching the revision under test instead of a stale asdf-installed release, and starts Katana with `--dev --dev.no-fee` so sozo migrate transactions aren't rejected by the mempool. The no-fee flag is needed because Katana's genesis block header is initialized with `GasPrices::MIN` (1 wei) while the live gas oracle used by mempool validation returns 20 gwei, and sozo (via starknet-rs) estimates fees against `BlockTag::Latest` which points to genesis right after startup, so the estimated max L1 gas price ends up at 1 wei and gets rejected against the oracle's 20 gwei floor. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
When a Starknet RPC node reports a
starknet_specVersionthat does not match the one sozo was built against (RPC_SPEC_VERSION = "0.9.0"), sozo aborted every command with:This blocks users whenever a node publishes a spec bump, even though most RPC methods sozo uses are stable across minor bumps. This PR replaces the hard error in
get_world_diff_and_providerwith aui.warn(...)and continues. If the node really is incompatible, the failure still surfaces at the actual RPC call site with a more specific error.Parse failures on the version string (malformed response) are also downgraded to a warning, for the same reason.
Changes
bin/sozo/src/utils.rs: replace the earlyreturn Err(...)on version mismatch with amatchthat emitsui.warn(...)for both mismatch and parse failure paths, then proceeds.is_compatible_version,RPC_SPEC_VERSION, and the 0.7/0.6 back-compat carve-out are unchanged.get_world_diff_and_provider.Test plan
cargo build -p sozosucceedscargo test -p sozo --bin sozo utils::tests::passes (5/5 — unchangedis_compatible_versiontests)🤖 Generated with Claude Code
Summary by CodeRabbit