microsoft/garnet · error · TsavoriteException

Consistent read context does not allow writes!

Error message

Consistent read context does not allow writes!

What it means

TransactionalConsistentReadContext rejects all write operations. This is the simplest Upsert overload (key, ReadOnlySpan<byte> value). Notably, this specific overload's message says 'Consistent read context does not allow writes!' (without the 'Transactional' prefix), unlike the neighboring overloads at lines 255+ which include 'Transactional'. This message inconsistency can mislead debugging — the throw originates from TransactionalConsistentReadContext but the message text matches ConsistentReadContext.

Source

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

        /// <inheritdoc/>
        public async ValueTask CompletePendingAsync(bool waitForCommit = false, CancellationToken token = default)
        {
            await TransactionalContext.CompletePendingAsync(waitForCommit, token).ConfigureAwait(false);
            Session.functions.PostSingleKeyConsistentReadCallback();
        }

        /// <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)]

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Call Upsert on session.TransactionalContext (for transactional writes with locking) or session.BasicContext instead.
  2. Note the message text inconsistency: this throw comes from TransactionalConsistentReadContext even though the message omits 'Transactional'.

Example fix

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

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

Strategy: validation

Validate before calling

// Route writes to TransactionalContext or BasicContext
// Note: the message text says 'Consistent read context' but this is TransactionalConsistentReadContext
session.TransactionalContext.Upsert(key, valueBytes);

Prevention

When it happens

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

Common situations: Code that uses transactional consistent-read sessions for read-heavy transactional workloads and accidentally routes an upsert through the same context; the inconsistent message text causing confusion during debugging about which context is active.

Related errors


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