WrongExpectedVersion with ExpectedVersion.Any

My understanding is that expectedVersion.Any should never fail with a WrongExpectedVersion because all idempotency checks are off as listed in http://docs.geteventstore.com/dotnet-api/3.0.3/optimistic-concurrency-and-idempotence/ where it says “This disables the optimistic concurrency check.”

Yet occassionally we’ll see an error like:

Message with id
6d4a4a40-83b6-5f2c-999a-8e462631ab59 found in position 513 in stream
Xi::IntegrationContainerReceived failed with reason Append failed due to
WrongExpectedVersion. Stream:
Xi::MidAmericanIL-ReceivedPackage_4fd7e767c9b85b5c8de8fefb8769b9c9, Expected
version: -2.

Stack trace is:

at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean
includeTaskCanceledExceptions) at System.Threading.Tasks.Task.Wait(Int32
millisecondsTimeout, CancellationToken cancellationToken) at
System.Threading.Tasks.Task.Wait() at
Realgy.ExternalIntegration.Infrastructure.Aggregate.EventStore.Repository1.SaveAll(Guid origEventId, String srvcName, Dictionary2 metaData) at
Realgy.ExternalIntegration.Infrastructure.Aggregate.EventStore.Repository1.SaveAll(ResolvedEvent origEvent, String srvcName) at Realgy.ExternalIntegration.Partner.ILEdiCommon.Handlers.BaseDecontainerService1.WorkMethod(IntegrationContainerReceived
srcEvent, HandleEventsContext ctx) at
Realgy.ExternalIntegration.Infrastructure.Reactive.Host.EventStoreIHandleWrapper1.onNextWorkAction(ResolvedEvent req, IEventStoreConnection esConn) in c:\Builds\2\RealgyFirst\XiProduction\src\RealgyFirst\Xi\Production\Infrastructure\Rx\ReactiveHost\EventStoreIHandleWrapper.cs:line 26 at Realgy.ExternalIntegration.Infrastructure.EventStore.RxExtensions.EventStoreObserver1.OnNext(ResolvedEvent
srcEvent) in c:\Builds\2\RealgyFirst\XiProduction\src\RealgyFirst\Xi\Production\Infrastructure\EventStore\EventStoreReactive\EventStoreObserver.cs:line
62 at
Realgy.ExternalIntegration.Infrastructure.EventStore.RxExtensions.EventStoreObserverWithExceptionCatch.OnNext(ResolvedEvent
srcEvent) in c:\Builds\2\RealgyFirst\XiProduction\src\RealgyFirst\Xi\Production\Infrastructure\EventStore\EventStoreReactive\EventStoreObserverWithExceptionCatch.cs:line
25

looking at the stream all the events appear to be written at the same time (and we do not have any retry logic).

Can you help me understand what I’m missing?

The stack trace doesn't really help to much as its mostly your code

How are you writing? What were you writing what was the message id and
reading from the exception what was the message id @ 513? I'm guessing
you hit an edge condition around an idempotency check where you are
reusing ids but in different batches?

Sorry it’s pretty straight forward.
How we’re writting:
Create deterministic id based on index, CausationEventId, and serviceName, serialize to bytes a straight AppendToStreamAsync and then Wait.

I’ve posted a ‘gist’ @ https://gist.github.com/kstrauss/3cd8c1bc3e74ddcf31cc

What I was writing:

5 events in the single append

Source EventId is 6d4a4a4083b65f2c999a8e462631ab59

Any other information needed?

We are doing an AppendToStream for each aggregate that has changes, so it would be to a different destination stream, but yes you could have the same Id generated/reused but written to different streams.

In the message it mentioned a conflict to a specific event 513 in the stream. Did you check the id you were writing vs the event in stream?

The new stream in theory should not have previously existed. If it did previously exist the event Ids should have been the same (I understand that means we could have had duplicate events written to the stream, because we have ExpectedVersion.Any). So it should have written 5 events as a block to the new stream of Xi::MidAmericanIL-ReceivedPackage_4fd7e767c9b85b5c8de8fefb8769b9c9. I’m not understanding under what conditions this should fail using ExpectedVersion.Any (assuming it could write).

Idempotency checks and different batch sizes is the one I am looking at.

eg I write 5 events in a batch id 11,13,88,22,99
then I write 3 events in a batch 88,8,145

It will actually return an expected version violation here as although
its trying to be idempotent the idempotency check doesn't fully match
up.

I am guessing on this edge case but would have to get an exact repro
with your data (assuming you can reproduce) to verify. It is a case
that it can return a wrong expected version. To be fair this scenario
should also never happen as its no longer an idempotent write its
basically a client error :slight_smile:

Cheers,

Greg