Repository navigation
Let applications register their own exception transforms (#5682) - #5750
Merged
Merged
Conversation
StoreOptions.Advanced.ExceptionTransforms (JasperFx.Core.Exceptions.ExceptionTransforms) is consulted for every database failure the store reports, after the failing operations' own transforms and BEFORE Marten's built-ins, whose NpgsqlException -> MartenCommandException catch-all would otherwise swallow it. Per store, never process-wide. Wired through SessionOptions into every connection lifetime (command, batch, ambient, external, auto-closing, RLS), the SaveChanges batch, the LINQ provider and the document cleaner. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merged
This was referenced Oct 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #5682.
This is the API the issue proposed, verbatim.
ExceptionTransformsis JasperFx's existingJasperFx.Core.Exceptions.ExceptionTransforms, the same typeMartenExceptionTransformeralready uses.Order
StoreOptions.Advanced.ExceptionTransforms.NpgsqlException→MartenCommandExceptioncatch-all.An error the application doesn't claim falls through unchanged. One it claims that Marten also translates, such as
40001, uses the application's translation for that store, which the XML docs say.Per store, not static
MartenExceptionTransformer.Transformsis a process-wide static, so registering there would have leaked between stores. The application's transforms are carried fromStoreOptionsthroughSessionOptionsintoConnectionLifetimeBase, and each lifetime picks them up in its constructor:TransactionalConnection,AutoClosingLifetime,AmbientTransactionLifetime,ExternalTransactionand their read-only and RLS subclasses. Every place that ran the built-ins now runs them in that order:DocumentSessionBase.SaveChanges;Binary compatibility: the only public change is one new get-only property on
AdvancedOptions. Everything else is internal.Tests
CoreTests.application_exception_transformscreates aplpgsqlguard that raisesCT001:QueueSqlCommandin the committing batch (the issue's case) →GuardRefusedException;BeforeSaveChangesAsync→GuardRefusedException;QueryAsync<int>→GuardRefusedException;MatchesSql→GuardRefusedException;42703) → stillMartenCommandException;MartenCommandException, so nothing leaks between stores.A/B: with the property present but the wiring stashed, the first four fail and the last two pass. With the change, all six pass. Regression runs (net10.0, PG 17):
DocumentDbTests.Concurrency: 52 passed.Docs: a new "Translating Database Errors into Your Own Exceptions" section in
docs/configuration/storeoptions.md; markdownlint and cspell are clean.🤖 Generated with Claude Code