Skip to content

Merge OnException handlers for the same exception type into one catch clause - #5357

Merged
jeremydmiller merged 3 commits into
JasperFx:mainfrom
esond:onexception-same-type-catch
Nov 5, 2026
Merged

jeremydmiller merged 3 commits into
JasperFx:mainfrom
esond:onexception-same-type-catch

Conversation

@esond

@esond esond commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

Two middleware types that each declare OnException for the same exception type made every handler they apply to fail code generation with CS0160, because TryCatchFinallyFrame added a second catch clause for that type. One way to hit it is MapMartenConcurrencyFailuresToConflict() next to an app's own ConcurrencyException middleware.

TryCatchFinallyFrame.AddCatchBlock now adds a later handler for a type that is already caught to the existing clause. The variables the handler creates get names that no earlier handler in that clause uses, so two handlers that return values don't declare the same local twice (CS0128).

  • The handlers run in registration order. If one ends the request or rethrows, the later ones don't run, the same as a Before that stops the chain. If you'd rather have a startup error naming both middlewares, I can switch to that.
  • Chains without a duplicate type generate the same code as before.
  • The new tests (void, cascading and HandlerContinuation handlers) fail on main and pass with the fix. Full CoreTests pass on net10.0.
  • A middleware OnException that returns a tuple still doesn't compile, even on its own. That's A middleware OnException that returns a tuple generates code that doesn't compile #5356.

esond added 2 commits November 4, 2026 22:46
… clause

Two middleware types that handled the same exception type generated two catch clauses for it, and the handler failed to compile with CS0160. A later handler for a type that is already caught now joins the existing clause, and the variables it creates get names no earlier handler in that clause uses. The handlers run in registration order until one of them ends the request or rethrows.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-05T05:04:40.374730Z c878c19 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c878c19c19

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Both cascaded messages in both_handlers_can_return_a_value can be handled
in parallel off the local queue, and concurrent List<T>.Add can drop one.
@jeremydmiller
jeremydmiller merged commit 1187260 into JasperFx:main Nov 5, 2026
@jeremydmiller

Copy link
Copy Markdown
Member

Thanks, merged. Merging into one catch clause is the right call; a startup error would penalize a legitimate setup like MapMartenConcurrencyFailuresToConflict() next to an app's own ConcurrencyException middleware. Running the handlers in registration order, with an early exit stopping the rest just as a Before does, matches how the rest of the middleware pipeline behaves. I'll add a note to the middleware docs about the ordering.

jeremydmiller added a commit that referenced this pull request Nov 5, 2026
#5357)

Two middleware OnException methods for one exception type now share a catch
block in registration order, and an early exit stops the rest. The docs say so,
and recommend an explicit try/catch where the order is in doubt, plus checking
the generated code with codegen preview/write.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCggXgxnG3EBXoR9rrq37U
jeremydmiller added a commit that referenced this pull request Nov 5, 2026
Follow-ups: Kafka replay GroupId docs + kafka-replay --group-id (#5306), same-type OnException docs (#5357)
@esond
esond deleted the onexception-same-type-catch branch November 5, 2026 18: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.

2 participants