{"record":{"id":"615119c09932fdf9","repo":"microsoft/garnet","slug":"transactional-consistent-read-context-does-not-all-615119","errorCode":null,"errorMessage":"Transactional consistent read context does not allow IsModified!","messagePattern":"Transactional consistent read context does not allow IsModified!","errorType":"exception","errorClass":"TsavoriteException","httpStatus":null,"severity":"error","filePath":"libs/storage/Tsavorite/cs/src/core/ClientSession/TransactionalConsistentReadContext.cs","lineNumber":389,"sourceCode":"        /// <inheritdoc/>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Status Delete(TKey key, TContext userContext = default)\n            => throw new TsavoriteException(\"Transactional consistent read context does not allow writes!\");\n\n        /// <inheritdoc/>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public Status Delete(TKey key, ref DeleteOptions deleteOptions, TContext userContext = default)\n            => throw new TsavoriteException(\"Transactional consistent read context does not allow writes!\");\n\n        /// <inheritdoc/>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        public void ResetModified(TKey key)\n            => throw new TsavoriteException(\"Transactional consistent read context does not reset ResetModified!\");\n\n        /// <inheritdoc/>\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        internal bool IsModified(TKey key)\n            => throw new TsavoriteException(\"Transactional consistent read context does not allow IsModified!\");\n\n        /// <inheritdoc/>\n        public void Refresh()\n            => throw new TsavoriteException(\"Transactional consistent read context does not Refresh!\");\n\n        #endregion ITsavoriteContext\n    }\n}","sourceCodeStart":371,"sourceCodeEnd":397,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/storage/Tsavorite/cs/src/core/ClientSession/TransactionalConsistentReadContext.cs#L371-L397","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Query IsModified only on a write-capable context: TransactionalUnsafeContext.IsModified (TransactionalUnsafeContext.cs:503) or the basic/unsafe equivalents.","Do not call modification-tracking queries against a read-only consistent read context.","If you are using reflection over all context types, skip TransactionalConsistentReadContext for IsModified."],"exampleFix":"// before (internal access)\nvar tcr = session.TransactionalConsistentReadContext;\nbool m = tcr.IsModified(key); // throws\n\n// after\nvar luc = session.TransactionalUnsafeContext;\nluc.BeginUnsafe();\ntry { bool m = luc.IsModified(key); }\nfinally { luc.EndUnsafe(); }","handlingStrategy":"validation","validationCode":"// IsModified is internal; only query it on a write-capable context.\nvar w = session.TransactionalUnsafeContext;\nw.BeginUnsafe();\ntry { bool m = w.IsModified(key); }\nfinally { w.EndUnsafe(); }","typeGuard":"static bool IsReadOnlyContext<TCtx>() => typeof(TCtx).Name.Contains(\"ConsistentReadContext\");\n// In internal tooling iterating context types, skip ConsistentReadContext for IsModified.","tryCatchPattern":null,"preventionTips":["IsModified has no meaning on a read-only snapshot.","Query it only via TransactionalUnsafeContext or basic/unsafe contexts.","Exclude read-only contexts from reflection-based modification-tracking sweeps."],"tags":["tsavorite","transaction","read-only-context","ismodified","internal","csharp"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}