Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

fix(rivetkit): expose engine ray IDs on errors#5456

Open
abcxff wants to merge 3 commits into
mainrivet-dev/rivet:mainfrom
fix/riveterror-ray-idrivet-dev/rivet:fix/riveterror-ray-idCopy head branch name to clipboard
Open

fix(rivetkit): expose engine ray IDs on errors#5456
abcxff wants to merge 3 commits into
mainrivet-dev/rivet:mainfrom
fix/riveterror-ray-idrivet-dev/rivet:fix/riveterror-ray-idCopy head branch name to clipboard

Conversation

@abcxff

@abcxff abcxff commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • expose x-rivet-ray-id as the top-level RivetError.rayId field without changing application error metadata
  • preserve Ray IDs through HTTP decoding, retries, remapping, scheduling errors, WebSocket close errors, reload failures, and TS/NAPI bridge round trips
  • include Ray IDs in structured HTTP error logs and document the expanded NAPI error payload

No Trace ID support or engine response contract changes are included.

Testing

  • pnpm exec vitest run tests/rivet-error.test.ts
  • pnpm run check-types in rivetkit-typescript/packages/rivetkit
  • Biome check on touched TypeScript files
  • git diff --check

Environment limitations

  • The driver matrix could not start in the orb because @rivetkit/engine-cli-linux-x64-musl is unavailable.
  • The NAPI Rust test was added but could not run because Cargo/rustfmt are not installed in the orb.

@railway-app
railway-app Bot temporarily deployed to rivet-frontend / rivet-pr-5456 July 21, 2026 02:30 Destroyed
@claude

claude Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review

(Re-checked against the current head, cac9589 — the only commit added since my last pass, 3cac1579, only touches tests/rivet-error.test.ts, so the findings below still apply and one new item is added.)

Overall this remains a clean, well-scoped change: rayId is threaded consistently through RivetError, the client fetch/WebSocket/retry paths, deconstructError, and the NAPI bridge round trip, with solid unit test coverage (round-trip encode/decode, metadata isolation, HTTP header attachment, Rust bridge payload round trip). Style matches repo conventions (structured tracing fields, hard tabs in Rust, explicit enum matching, etc.).

Still open: the actor's own HTTP router never emits rayId

common/router.ts::handleRouteError (rivetkit-typescript/packages/rivetkit/src/common/router.ts:63-101) destructures { statusCode, group, code, message, metadata, actor } from deconstructError(...) but drops rayId before building errorData, and no x-rivet-ray-id header is set on the response here (unlike the gateway/engine responses this PR's client code already reads that header from). So a RivetError raised inside an actor (e.g. an internal KV/SQL/engine call that failed and carried an engine ray ID, now preserved on the error object by this PR) survives all the way through deconstructError and is then silently discarded at serialization. This is the one direction the PR's stated goal ("preserve Ray IDs through HTTP decoding... scheduling errors... reload failures") doesn't cover — it holds for errors decoded on the client from gateway/engine responses, not for errors an actor raises and returns through its own router.

Still open: the default sanitized-error branch also drops rayId

In common/utils.ts::deconstructError (rivetkit-typescript/packages/rivetkit/src/common/utils.ts:132-144), the final else branch — hit whenever exposeInternalError is false and the error isn't public (the default in production) — builds the generic opaque INTERNAL_ERROR_DESCRIPTION response. It preserves actor when available but never assigns rayId. Since a ray ID is meant to be a safe, non-sensitive correlation handle, this is exactly the branch where surfacing it would be most valuable — an opaque 500 with no other diagnostic info. Worth adding rayId = error.rayId here too (and plumbing it out through handleRouteError above) to fully close the loop.

New: wasm bridge (rivetkit-wasm) doesn't get the same rayId plumbing as NAPI

rivetkit-typescript/packages/rivetkit-wasm/src/lib.rs has its own copy of the bridge machinery this PR modifies in rivetkit-napi (BridgeRivetErrorPayload, BridgeRivetErrorContext, anyhow_to_bridge_rivet_error_payload, parse_bridge_rivet_error), but none of it was updated:

  • BridgeRivetErrorPayload (line 60) and BridgeRivetErrorContext (line 73) have no ray_id/rayId field, so parse_bridge_rivet_error (line 2989) silently drops any rayId key present in JSON coming from the shared TS glue (registry/native.ts::encodeNativeCallbackError, which this PR did update to include rayId).
  • anyhow_to_bridge_rivet_error_payload in lib.rs (line 3076) never emits a rayId key back to JS, unlike the NAPI version this PR just changed at rivetkit-napi/src/lib.rs:100.

Net effect: on the wasm runtime, ray IDs get dropped in both directions across the JS↔Rust bridge, even though the wire format and TS-side code are shared with NAPI. Given the repo's general NAPI/wasm parity expectations for this bridge, this looks like a gap worth closing in this PR or tracking as an explicit follow-up (the PR description doesn't mention it).

Minor / non-blocking

  • rivetkit-napi/src/actor_context.rs's verify_inspector_auth_js change (ray_id: None) is correct as-is — that's a locally generated 401 with no upstream ray ID.
  • Test coverage for the client-header path and the Rust bridge round trip is solid; per the PR description, the NAPI Rust test and driver matrix couldn't actually be run in the author's environment, so confirm CI runs cargo test -p rivetkit-napi (and, per the wasm point above, cargo test -p rivetkit-wasm if a parity fix lands) before merge.

No security or performance concerns — this is metadata plumbing over already-established boundaries (the x-rivet-ray-id header itself is pre-existing), and no unbounded/sensitive data is added to logs or metrics.

@railway-app

railway-app Bot commented Jul 21, 2026

Copy link
Copy Markdown

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

Service Status Web Updated (UTC)
frontend-cloud 😴 Sleeping (View Logs) Web Jul 24, 2026 at 4:10 pm
kitchen-sink 😴 Sleeping (View Logs) Web Jul 22, 2026 at 3:42 pm
frontend-inspector 😴 Sleeping (View Logs) Web Jul 22, 2026 at 3:41 pm
website 😴 Sleeping (View Logs) Web Jul 22, 2026 at 3:40 pm
ladle ✅ Success (View Logs) Web Jul 22, 2026 at 3:34 pm
mcp-hub ✅ Success (View Logs) Web Jul 22, 2026 at 3:31 pm

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.

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.