microsoft/garnet · error · TsavoriteException

Transactional consistent read context does not allow IsModif

Error message

Transactional consistent read context does not allow IsModified!

What it means

IsModified (line 389) throws on TransactionalConsistentReadContext with 'does not allow IsModified!' because the read-only snapshot never accumulates per-key modification state, so the query has no defined answer. Note it is internal, so external code triggers it only via reflection or an internal friend assembly.

Source

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

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

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

        /// <inheritdoc/>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void ResetModified(TKey key)
            => throw new TsavoriteException("Transactional consistent read context does not reset ResetModified!");

        /// <inheritdoc/>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal bool IsModified(TKey key)
            => throw new TsavoriteException("Transactional consistent read context does not allow IsModified!");

        /// <inheritdoc/>
        public void Refresh()
            => throw new TsavoriteException("Transactional consistent read context does not Refresh!");

        #endregion ITsavoriteContext
    }
}

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Query IsModified only on a write-capable context: TransactionalUnsafeContext.IsModified (TransactionalUnsafeContext.cs:503) or the basic/unsafe equivalents.
  2. Do not call modification-tracking queries against a read-only consistent read context.
  3. If you are using reflection over all context types, skip TransactionalConsistentReadContext for IsModified.

Example fix

// before (internal access)
var tcr = session.TransactionalConsistentReadContext;
bool m = tcr.IsModified(key); // throws

// after
var luc = session.TransactionalUnsafeContext;
luc.BeginUnsafe();
try { bool m = luc.IsModified(key); }
finally { luc.EndUnsafe(); }
Defensive patterns

Strategy: validation

Validate before calling

// IsModified is internal; only query it on a write-capable context.
var w = session.TransactionalUnsafeContext;
w.BeginUnsafe();
try { bool m = w.IsModified(key); }
finally { w.EndUnsafe(); }

Type guard

static bool IsReadOnlyContext<TCtx>() => typeof(TCtx).Name.Contains("ConsistentReadContext");
// In internal tooling iterating context types, skip ConsistentReadContext for IsModified.

Prevention

When it happens

Trigger: Calling the internal tcrContext.IsModified(TKey key) on the transactional consistent read context, e.g. from an internal/friend assembly that checks whether a key was modified during a transactional read.

Common situations: Internal tooling or tests that exercise modification-tracking uniformly across all context types hit the read-only context, which has no modified set to query.

Related errors


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