Skip to content

Conversation

Monkatraz
Copy link
Contributor

Why

Fixes #333

In streaming procedures, you often need to push an uncaught error into the stream outside of the scope of the handler. This is tricky since all you're left with doing is manually returning an uncaught error rather than using any of the machinery River has built in.

What changed

Added ctx.uncaught which works a lot like ctx.cancel except that it uses UNCAUGHT_ERROR rather than the cancel code. It uses the exact same mechanism as the normal procedure error handler and yields you an error result that you can return if needed. It accepts anything as an argument so that you can use it ergonomically in a try catch.

Versioning

  • Breaking protocol change
  • Breaking ts/js API change

@Monkatraz Monkatraz requested a review from a team as a code owner July 15, 2025 18:09
@Monkatraz Monkatraz requested review from daweifeng-replit and removed request for a team July 15, 2025 18:09
cancel: (message?: string) => ErrResult<Static<typeof CancelErrorSchema>>;
/**
* This emits an uncaught error in the same way that throwing an error in a handler
* would. You should minimize the amount of work you do after calling this function
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we can create an eslint rule for this

/**
* This emits an uncaught error in the same way that throwing an error in a handler
* would. You should minimize the amount of work you do after calling this function
* as this will start a cleanup of the entire procedure call.
Copy link
Member

Choose a reason for hiding this comment

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

maybe clarify this ends the readable/writables

Comment on lines +48 to +49
* You'll typically want to use this for streaming procedures, as in e.g. an RPC
* you can just throw instead.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* You'll typically want to use this for streaming procedures, as in e.g. an RPC
* you can just throw instead.
* You'll typically want to use this for server-sent stream procedures like subscriptions or streams which may handle things inside closures where throwing will not be caught by River's procedure uncaught handler.

* You'll typically want to use this for streaming procedures, as in e.g. an RPC
* you can just throw instead.
*/
uncaught: (err?: unknown) => ErrResult<Static<typeof UncaughtErrorSchema>>;
Copy link
Member

Choose a reason for hiding this comment

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

what does it mean to throw an uncaught with no err?

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.

Allow "throwing" in server streams

3 participants