What happens
The SQLite lightweight saga storage throws a bare System.Exception when an optimistic-concurrency update touches zero rows:
// src/Persistence/Wolverine.Sqlite/Sagas/DatabaseSagaSchema.cs:188
if (count == 0)
{
throw new Exception(
$"Saga version mismatch for {typeof(T).FullName} with id {id}. Possible concurrent update detected.");
}
Every other lightweight saga provider throws SagaConcurrencyException at the same point (Postgres DatabaseSagaSchema.cs:107, SQL Server :113, MySQL :118, Oracle OracleSagaSchema.cs:143), as do the EF Core (EFCorePersistenceFrameProvider.cs:925), CosmosDB, S3 and Azure Blob saga paths. SagaConcurrencyException derives from JasperFx.ConcurrencyException (GH-3444) precisely so that one OnException<ConcurrencyException>() policy covers saga concurrency failures on every provider.
Why it matters
Wolverine's failure-rule matching is ex is T. The recommended policy for optimistic concurrency, OnException<ConcurrencyException>().RetryWithCooldown(...), matches on every provider except SQLite, where the bare Exception falls through to the default MoveToErrorQueue continuation. Same code, same saga, different outcome depending on which package is referenced. That also affects Fisher-backed hosts, since Wolverine.Fisher composes over the SQLite persistence.
Fix
Throw SagaConcurrencyException with the same message shape the other providers use, so the wording is uniform too:
throw new SagaConcurrencyException(
$"Saga of type {typeof(T).FullNameInCode()} and id {id} cannot be updated because of optimistic concurrency violations");
A test mirroring the Postgres/SQL Server saga concurrency test for the SQLite provider would pin it.
What happens
The SQLite lightweight saga storage throws a bare
System.Exceptionwhen an optimistic-concurrency update touches zero rows:Every other lightweight saga provider throws
SagaConcurrencyExceptionat the same point (PostgresDatabaseSagaSchema.cs:107, SQL Server:113, MySQL:118, OracleOracleSagaSchema.cs:143), as do the EF Core (EFCorePersistenceFrameProvider.cs:925), CosmosDB, S3 and Azure Blob saga paths.SagaConcurrencyExceptionderives fromJasperFx.ConcurrencyException(GH-3444) precisely so that oneOnException<ConcurrencyException>()policy covers saga concurrency failures on every provider.Why it matters
Wolverine's failure-rule matching is
ex is T. The recommended policy for optimistic concurrency,OnException<ConcurrencyException>().RetryWithCooldown(...), matches on every provider except SQLite, where the bareExceptionfalls through to the defaultMoveToErrorQueuecontinuation. Same code, same saga, different outcome depending on which package is referenced. That also affects Fisher-backed hosts, since Wolverine.Fisher composes over the SQLite persistence.Fix
Throw
SagaConcurrencyExceptionwith the same message shape the other providers use, so the wording is uniform too:A test mirroring the Postgres/SQL Server saga concurrency test for the SQLite provider would pin it.