Skip to content

fix(rivetkit): expose engine ray IDs on errors for debug - #5603

Open
abcxff wants to merge 1 commit into
stack/fix-frontend-submit-vercel-drain-grace-period-qnpvtqqzfrom
stack/fix-rivetkit-expose-engine-ray-ids-on-errors-for-debug-kzmlwrll
Open

fix(rivetkit): expose engine ray IDs on errors for debug#5603
abcxff wants to merge 1 commit into
stack/fix-frontend-submit-vercel-drain-grace-period-qnpvtqqzfrom
stack/fix-rivetkit-expose-engine-ray-ids-on-errors-for-debug-kzmlwrll

Conversation

@abcxff

@abcxff abcxff commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@abcxff

abcxff commented Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

Stack for rivet-dev/actors

Get stack: forklift get 5603
Push local edits: forklift submit
Merge when ready: forklift merge 5603

change kzmlwrll

@railway-app

railway-app Bot commented Aug 25, 2026

Copy link
Copy Markdown

🚅 Deployed to the actors-pr-5603 environment in rivet-frontend

Service Status Web Updated (UTC)
frontend-cloud 😴 Sleeping (View Logs) Web Aug 31, 2026 at 3:44 am
website ❌ Build Failed (View Logs) Web Aug 31, 2026 at 1:40 am
frontend-inspector 😴 Sleeping (View Logs) Web Aug 29, 2026 at 12:50 pm
kitchen-sink 😴 Sleeping (View Logs) Web Aug 27, 2026 at 3:31 pm
ladle ✅ Success (View Logs) Web Aug 25, 2026 at 7:29 pm
mcp-hub ✅ Success (View Logs) Web Aug 25, 2026 at 7:27 pm

@claude

claude Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Review

Reviewed the ray-ID-on-errors plumbing (rayId threaded from the engine through the NAPI bridge, HTTP x-rivet-ray-id header, WebSocket close-reason suffix, deconstructError, RivetError, and the @rivetkit/effect wrapper). Overall the change is clean, consistent, and well-tested (round-trip encode/decode test, null-coercion test, HTTP header propagation test).

Finding

rivetkit-typescript/packages/rivetkit/src/actor/errors.ts:73 - looksLikeRivetErrorOptions now also treats any object containing a top-level rayId key as RivetErrorOptions instead of bare metadata:

function looksLikeRivetErrorOptions(value: unknown): value is RivetErrorOptions {
	return (
		typeof value === "object" &&
		value !== null &&
		("public" in value ||
			"metadata" in value ||
			"rayId" in value ||   // newly added by this PR
			"statusCode" in value ||
			"actor" in value ||
			"cause" in value)
	);
}

RivetError/ActorError is a public export, and its constructor supports a legacy calling convention where the whole 4th argument is treated as bare metadata when it does not look like RivetErrorOptions ({ metadata: options }). If a caller does new RivetError(group, code, message, someMetadataObject) where someMetadataObject happens to contain a rayId property (plausible now that "ray ID" is a generic-sounding field name for app-level request correlation), it gets misclassified as options: this.rayId picks up the caller's application value instead of the engine-correlated ray ID, and this.metadata becomes undefined, silently dropping the caller's intended metadata payload.

This mirrors a pre-existing ambiguity in the heuristic (the same risk already exists for actor/cause/statusCode), but rayId widens the collision surface with a new, generically-named key right as the PR is establishing rayId as an engine-reserved concept. Worth either handling this more strictly (e.g. only using the bare-metadata fallback for genuinely untyped callers, or namespacing engine-injected fields) or documenting that metadata objects must avoid this key. Not blocking since it requires a fairly specific field-name collision, but worth a test case and/or doc note given the PR is actively growing this same list.

Everything else checked out

  • NAPI Rust to JS rayId round trip (Option<String> to null coercion) is handled correctly on both sides.
  • HTTP header (x-rivet-ray-id) and WS close-reason (rayId suffix after the delimiter) extraction paths are consistent and always take precedence over any body-embedded value.
  • All call sites constructing ActorError/RivetError after this change pass rayId through explicitly; no missed propagation sites found.
  • Test coverage is solid for the new behavior (bridge round-trip, null-ray-id decode, HTTP-header-to-thrown-error propagation, metadata/rayId non-collision in the options-object calling convention).

@abcxff
abcxff force-pushed the stack/fix-rivetkit-expose-engine-ray-ids-on-errors-for-debug-kzmlwrll branch from 3607ab1 to 9852405 Compare August 31, 2026 01:40
@abcxff
abcxff force-pushed the stack/fix-frontend-submit-vercel-drain-grace-period-qnpvtqqz branch from 52e63fd to 229337b Compare August 31, 2026 01:40
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