microsoft/garnet · error · TsavoriteException

Transactional consistent read context does not allow writes!

Error message

Transactional consistent read context does not allow writes!

What it means

TransactionalConsistentReadContext rejects writes to preserve its snapshot-isolation guarantee within a transactional session. This overload accepts UpsertOptions (for TTL, ETag, etc.). The message correctly includes 'Transactional' prefix ('Transactional consistent read context does not allow writes!'), unlike the simpler overload at line 250. The throw is unconditional.

Source

Thrown at libs/storage/Tsavorite/cs/src/core/ClientSession/TransactionalConsistentReadContext.cs:255

        }

        /// <inheritdoc/>
        public async ValueTask<CompletedOutputIterator<TInput, TOutput, TContext>> CompletePendingWithOutputsAsync(bool waitForCommit = false, CancellationToken token = default)
        {
            var status = await TransactionalContext.CompletePendingWithOutputsAsync(waitForCommit, token).ConfigureAwait(false);
            Session.functions.PostSingleKeyConsistentReadCallback();
            return status;
        }

        /// <inheritdoc/>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public Status Upsert(TKey key, ReadOnlySpan<byte> desiredValue, TContext userContext = default)
            => throw new TsavoriteException("Consistent read context does not allow writes!");

        /// <inheritdoc/>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public Status Upsert(TKey key, ReadOnlySpan<byte> desiredValue, ref UpsertOptions upsertOptions, TContext userContext = default)
            => throw new TsavoriteException("Transactional consistent read context does not allow writes!");

        /// <inheritdoc/>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public Status Upsert(TKey key, ref TInput input, ReadOnlySpan<byte> desiredValue, ref TOutput output, TContext userContext = default)
            => throw new TsavoriteException("Transactional consistent read context does not allow writes!");

        /// <inheritdoc/>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public Status Upsert(TKey key, ref TInput input, ReadOnlySpan<byte> desiredValue, ref TOutput output, ref UpsertOptions upsertOptions, TContext userContext = default)
            => throw new TsavoriteException("Transactional consistent read context does not allow writes!");

        /// <inheritdoc/>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public Status Upsert(TKey key, ref TInput input, ReadOnlySpan<byte> desiredValue, ref TOutput output, ref UpsertOptions upsertOptions, out RecordMetadata recordMetadata, TContext userContext = default)
            => throw new TsavoriteException("Transactional consistent read context does not allow writes!");

        public Status Upsert<TOpKey, TSourceLogRecord>(TOpKey key, in TSourceLogRecord diskLogRecord)
            where TOpKey : IKey

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Call this Upsert overload on session.TransactionalContext or session.BasicContext, not on TransactionalConsistentReadContext.
  2. Maintain clear separation: use TransactionalConsistentReadContext for reads-with-locking, TransactionalContext for writes-with-locking.

Example fix

// before (throws)
session.TransactionalConsistentReadContext.Upsert(key, valueBytes, ref upsertOpts);

// after
session.TransactionalContext.Upsert(key, valueBytes, ref upsertOpts);
Defensive patterns

Strategy: validation

Validate before calling

// Use TransactionalContext for transactional writes with options
session.TransactionalContext.Upsert(key, valueBytes, ref upsertOptions);

Prevention

When it happens

Trigger: Calling Upsert(TKey key, ReadOnlySpan<byte> desiredValue, ref UpsertOptions upsertOptions, TContext userContext) on session.TransactionalConsistentReadContext.

Common situations: Transactional read-heavy code paths that share a context variable and accidentally route upsert-with-options through the consistent-read transactional context.

Related errors


AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13). Data as JSON: /api/errors/5fafb52c247c51ae. Report an issue: GitHub.