Skip to content

Bump the weasel group with 1 update - #3994

Closed
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/nuget/weasel-7fd22671f3
Closed

dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/nuget/weasel-7fd22671f3

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Updated Marten from 9.40.0 to 9.41.0.

Release notes

Sourced from Marten's releases.

9.41.0

Upgrade if you use IsolationLevel.Serializable. The first item below is a silent lost update, and it has been present since the write-retry pipeline shipped. The two items after it change behaviour you may be relying on.

🛑 Data integrity: Serializable sessions could silently lose an update

#​5528. A session opened with IsolationLevel.Serializable (or RepeatableRead) did not reliably protect against a lost update. PostgreSQL detected the write conflict correctly and Marten discarded the detection by retrying.

Two serializable sessions each load the same document at Amount = 100. One commits 100 - 500. The other should be refused with ConcurrentUpdateException; instead it committed 100 - 350 on top, and the first session's write was gone with no error raised anywhere. From the server's own log:

[14197] ERROR:  could not serialize access due to concurrent update
[14197] ROLLBACK
[14196] BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE    -- the replay
[14196] insert ... on conflict (id) do update ...         -- same values, same mt_version
[14196] COMMIT

WriteRetryClassifier (#​5262) listed 40001 serialization_failure as safe to replay, on the reasoning that the server had rolled the transaction back and said so — which is true, and turned out to be necessary but not sufficient. A replay re-issues the operations already computed, rather than re-running the application code that produced them, and a serialization failure means precisely that the snapshot those operations were derived from is no longer a valid basis for them. The replay opens a new transaction with a fresh snapshot, so the conflict is gone and the write lands.

40001 is now never replayed and surfaces as ConcurrentUpdateException, which is what Marten already translated it to. If you opted into Serializable you should expect to start seeing that exception — handle it by re-reading and recomputing, which is the only place the conflict can be resolved. Nothing inside Marten requests these isolation levels, so the async daemon and every default ReadCommitted session are unaffected.

40P01 deadlock_detected stays retryable deliberately: a deadlock aborts over lock ordering rather than a rejected snapshot, and replaying it is the textbook remedy at ReadCommitted. A deadlock retry under Serializable replays stale-snapshot work for the same structural reason, and the honest fix needs the isolation level plumbed into the classifier — recorded as a known gap rather than guessed at.

This went unnoticed because the test that catches it lives in StressTests, which has had no CI job since 2026-08-08.

⚠️ Behaviour change: the HotCold leadership lock is session-scoped again

#​5526. Events.UseAdvisoryLockTransaction now defaults to false, so HotCold leader election uses a session-scoped pg_try_advisory_lock rather than a transaction-scoped pg_try_advisory_xact_lock. The transaction-scoped lock had been the default since 8.37.3 (April 2026).

The reason is what the transaction-scoped lock costs while it works: the leader holds an open transaction for as long as it holds leadership, which on a long-lived daemon is an indefinitely long-running transaction sitting on the connection — with everything that implies for vacuum and for anything watching transaction age.

The transaction-scoped lock is still the better fit behind PgBouncer in transaction pooling mode, which can hand a session-scoped lock's server connection to another client. If that is your deployment, opt back in explicitly:

builder.Services.AddMarten(opts =>
{
    opts.Connection(connectionString);
    opts.Events.UseAdvisoryLockTransaction = true;
})
.AddAsyncDaemon(DaemonMode.HotCold);

⚠️ Breaking: DefaultTenantUsageDisabledException is no longer a MartenException

#​5514. Marten.Exceptions.DefaultTenantUsageDisabledException now derives from JasperFx.Events.DefaultTenantUsageDisabledException.

JasperFx.Events carries this exception so that code can handle the refusal once across Critter Stack stores, and its own contract is that stores subclass it. Polecat did; Marten did not. The consequence was not an error anywhere — a store-agnostic catch (JasperFx.Events.DefaultTenantUsageDisabledException) compiled, read as if it handled the refusal, and let it through unhandled on Marten only. That is the failure mode this fixes.

Multiple inheritance is not available, so it is one base or the other, and the cross-store catch was judged worth more than the marker base. If you rely on a broad catch (MartenException) to handle this refusal, it will no longer be caught — catch the exception itself, or the JasperFx base. The message is unchanged, including the single-argument overload's behaviour of appending to the standard prefix.

Also gone with the reparenting: the protected (SerializationInfo, StreamingContext) constructor, because the JasperFx base declares none to chain to. Binary serialization of exceptions has been obsolete since .NET 8.
... (truncated)

Commits viewable in compare view.

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore <dependency name> major version will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
  • @dependabot ignore <dependency name> minor version will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
  • @dependabot ignore <dependency name> will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
  • @dependabot unignore <dependency name> will remove all of the ignore conditions of the specified dependency
  • @dependabot unignore <dependency name> <ignore condition> will remove the ignore condition of the specified dependency and ignore conditions

Bumps Marten from 9.40.0 to 9.41.0

---
updated-dependencies:
- dependency-name: Marten
  dependency-version: 9.41.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: weasel
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added .NET Pull requests that update .NET code dependencies Pull requests that update a dependency file labels Sep 29, 2026
@dependabot @github

dependabot Bot commented on behalf of github Oct 3, 2026

Copy link
Copy Markdown
Contributor Author

Looks like Marten is updatable in another way, so this is no longer needed.

@dependabot dependabot Bot closed this Oct 3, 2026
@dependabot
dependabot Bot deleted the dependabot/nuget/weasel-7fd22671f3 branch October 3, 2026 21:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file .NET Pull requests that update .NET code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants