Skip to content

fix(rivetkit): auto-spawn engine binary path on local endpoint#5263

Merged
NathanFlurry merged 10 commits into
mainfrom
fix-engine-autospawn-binary-path
Jun 14, 2026
Merged

fix(rivetkit): auto-spawn engine binary path on local endpoint#5263
NathanFlurry merged 10 commits into
mainfrom
fix-engine-autospawn-binary-path

Conversation

@NathanFlurry

@NathanFlurry NathanFlurry commented Jun 14, 2026

Copy link
Copy Markdown
Member

Problem

Running a RivetKit server locally with no env vars (e.g. registry.start() from hello-world) failed out-of-box on 2.3.0-rc.13:

engine.binary_unavailable: No usable engine binary was found for version '2.3.0-rc.13'.

The npm-installed engine binary is present, but the core never learns its path on the auto-spawn path.

Root cause

buildServeConfig (in registry/native.ts and registry/runtime.ts) only sets serveConfig.engineBinaryPath = getEnginePath() inside if (config.startEngine). But the Rust core auto-spawns a local engine for any loopback endpoint (EngineSpawnMode::Auto), independent of startEngine. So running locally without RIVET_RUN_ENGINE=1 auto-spawns but has no binary path.

Fixes in this PR

  1. fix(rivetkit): auto-spawn engine binary path — resolve engineBinaryPath whenever the core will manage a local engine (config.startEngine || isLocalEngineEndpoint(config.endpoint)), in both buildServeConfig implementations.
  2. fix(publish): bump Cargo.toml workspace dep pins during release cutcut-release.ts now bumps the version = "=X" internal-crate pins (it previously left them on the prior version, breaking the Rust/wasm build during a release cut).
  3. fix(publish): order envoy-protocol before depot-client; allow re-run when npm already publishedRUST_CRATES published rivet-depot-client before its exact dependency rivet-envoy-protocol, so crates.io publish always failed; and the npm release-mode guard hard-failed on re-runs after npm already published. Both blocked completing a release.
  4. fix(publish): add rivetkit-engine-process to crates publish listrivetkit-core depends on rivetkit-engine-process, which was missing from RUST_CRATES, so the crates publish failed at rivetkit-core.

Verification

Verified end-to-end against a standalone npm project on the published 2.3.0-rc.14 (which includes fix #1): the engine auto-spawns with no env var, and the full suite passes — HTTP, WebSocket + events, SQLite migrations/CRUD, state + SQLite persistence across restart, instance isolation, error propagation, message-size limits, tsx --watch hot reload, and the React client in a real browser. Fixes #2-#4 were validated by the 2.3.0-rc.14 release pipeline completing npm + crates.io + git tag + GitHub release.

🤖 Generated with Claude Code

@railway-app railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5263 June 14, 2026 17:50 Destroyed
@railway-app

railway-app Bot commented Jun 14, 2026

Copy link
Copy Markdown

🚅 Deployed to the rivet-pr-5263 environment in rivet-frontend

Service Status Web Updated (UTC)
frontend-cloud 😴 Sleeping (View Logs) Web Jun 14, 2026 at 10:11 pm
kitchen-sink ❌ Build Failed (View Logs) Web Jun 14, 2026 at 10:08 pm
frontend-inspector ❌ Build Failed (View Logs) Web Jun 14, 2026 at 10:00 pm
ladle ✅ Success (View Logs) Web Jun 14, 2026 at 9:35 pm
website 😴 Sleeping (View Logs) Web Jun 14, 2026 at 5:59 pm
mcp-hub ✅ Success (View Logs) Web Jun 14, 2026 at 5:50 pm

@claude

claude Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

PR Review: fix(rivetkit): auto-spawn engine binary path on local endpoint

47 additions / 9 deletions across 6 files - release-pipeline bug fixes and one runtime fix.


Summary

This PR fixes four distinct bugs discovered during the 2.3.0-rc.14 release:

  1. native.ts / runtime.ts - Engine binary path was only resolved inside if (config.startEngine), but rivetkit-core auto-spawns an engine for any loopback endpoint regardless of that flag. The fix unconditionally resolves the path and passes it to core, letting core decide whether it is needed.
  2. scripts/publish/src/ci/bin.ts - rivet-depot-client was published before rivet-envoy-protocol, which it pins as an exact dependency. Reordered to fix crates.io publish ordering. Also adds rivetkit-engine-process (missing optional dep of rivetkit-core) to the publish list.
  3. scripts/publish/src/lib/npm.ts - Changed hard failure to a warning when all packages are already published, enabling clean re-runs after a partial pipeline failure.
  4. cut-release.ts / version.ts - cut-release.ts called updateSourceFiles but never bumped the version = "=X" exact pins in [workspace.dependencies.*]. Added bumpCargoVersions call to fix this, and added rivetkit-engine-process to PUBLISHED_RUST_WORKSPACE_DEPS.

Code Quality

native.ts and runtime.ts - silent catch scope

The bare catch blocks swallow all exceptions from loadEngineCli() / loadEnginePath(), not just binary-not-found errors. If either throws for an unexpected reason (permissions issue, malformed module, etc.), the path is silently left unset and core emits engine.binary_unavailable, which is misleading if the real failure is something else. Consider logging at debug level to surface unexpected failures during development without changing production behavior.

cut-release.ts - redundant [workspace.package] write

Both updateSourceFiles and bumpCargoVersions write [workspace.package].version. The outcome is idempotent but the field is written twice per release cut. Worth consolidating in a follow-up.

npm.ts - warn vs. throw trade-off

The hard error becoming a warning is reasonable for re-run recovery, but if someone forgets to bump the version the pipeline continues silently. Consider whether an additional signal (e.g. verifying the git tag does not already exist) should gate forward progress.

cut-release.ts - comment style (minor)

The new comment uses a semicolon and a parenthetical (like updateSourceFiles). Per project conventions, comments should be complete sentences without parenthetical fragments.


Potential Bugs

bin.ts - verify rivetkit-engine-process transitive deps

rivetkit-engine-process is inserted immediately before rivetkit-core. If it has any internal crate deps not already earlier in the list, those would need to precede it too. Worth confirming its Cargo.toml internal deps are all published earlier in RUST_CRATES.

version.ts - regex robustness for new dep entry

The regex for [workspace.dependencies.X] pins requires version = to appear before any blank lines after the section header. Worth verifying the rivetkit-engine-process entry in Cargo.toml matches the expected format.


Security

No concerns. Changes do not touch authentication, authorization, or data handling.

Test Coverage

No unit tests added, but the nature of these fixes makes automated coverage difficult. The described end-to-end validation against a standalone npm project is appropriate.


Overall Assessment

The fixes are correct and address real, verified bugs that blocked a release. The core fix (unconditional engine path resolution) is sound. The publish ordering and missing-crate fixes are straightforward.

Actionable items:

  1. Consider logging the caught exception in native.ts / runtime.ts at debug level.
  2. Consolidate the duplicate [workspace.package] write in a follow-up.
  3. Consider an additional gate in npm.ts to catch forgotten version bumps.

Otherwise, this looks good to merge.

… before depot-client; allow re-run when npm already published
@railway-app railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5263 June 14, 2026 19:56 Destroyed
…fort pass engine binary path; core owns spawn decision
@railway-app railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5263 June 14, 2026 20:32 Destroyed
@railway-app railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5263 June 14, 2026 21:33 Destroyed
@claude

claude Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

PR Review: fix(rivetkit): auto-spawn engine binary path on local endpoint

Overall this is a well-scoped fix for a real regression. The primary bug is clearly diagnosed and the fix is correct.


Primary fix: native.ts / runtime.ts

Correct. Moving engineBinaryPath resolution outside the if (config.startEngine) guard is the right call. The engine can auto-spawn for any loopback endpoint regardless of startEngine, so core needs the binary path unconditionally. The try/catch is appropriate: binary resolution can legitimately fail on remote-only installs or unsupported platforms, and core is the authority on whether a binary is actually needed.

Moving engineHost / enginePort out of the guard is also correct. These are connection parameters, not binary-availability parameters, and should always be set when a local engine is in play.

Issue: em dashes in warning messages. Per CLAUDE.md, em dashes should not appear in plain-English writing. The warning strings in both native.ts and runtime.ts contain em dashes. Use a period or semicolon instead.


isVersionAtLeast 0.0.0 bypass (actor-inspector-context.tsx)

Clean and well-scoped. The 0.0.0 fast-path correctly handles dev/preview builds from pkg.pr.new or branch snapshots.


Publish script fixes (bin.ts, npm.ts, version.ts, cut-release.ts)

  • RUST_CRATES ordering (bin.ts): Correct. rivet-envoy-protocol must precede rivet-depot-client since depot-client pins it as an exact dep. Adding rivetkit-engine-process before rivetkit-core follows the same invariant.
  • PUBLISHED_RUST_WORKSPACE_DEPS (version.ts): Adding rivetkit-engine-process is consistent and necessary for cut-release.ts to bump exact version pins correctly.
  • Cargo version bump (cut-release.ts): The missing bumpCargoVersions call was a real gap. Without it, internal exact pins remained at the old version and broke the wasm build.
  • warn-instead-of-throw (npm.ts): Pragmatically reasonable for re-run support. Trade-off: a forgotten version bump in a clean run now yields only a warning rather than a failure. Acceptable given the release CI re-run scenario this targets.

Dockerfile and turbo.json

The build:inspector-ui Turborepo task inputs look complete. SKIP_NAPI_BUILD=1 and SKIP_WASM_BUILD=1 correctly avoid triggering Rust builds in the frontend-only Docker step. The pattern is consistent across all 7 platform Dockerfiles.


Summary

The em dash issue in warning messages is the only actionable item. All other changes are correct and well-reasoned.

…ia turbo so rivetkit builds first in napi image
@railway-app railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5263 June 14, 2026 21:46 Destroyed
…or-ui from napi build.mjs (inverts dep order)
@railway-app railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5263 June 14, 2026 21:59 Destroyed
@NathanFlurry NathanFlurry merged commit da704d8 into main Jun 14, 2026
32 of 37 checks passed
@NathanFlurry NathanFlurry deleted the fix-engine-autospawn-binary-path branch June 14, 2026 22:17
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.

[SVC-2479] Send cluster events to PostHog [SVC-2555] Set up issue templates

1 participant