microsoft/garnet · error · GarnetException

Failed to acquire inProgress lock at {nameof(PreBatchKeyCons

Error message

Failed to acquire inProgress lock at {nameof(PreBatchKeyConsistentReadCallback)}

What it means

Thrown by ReplicaReadSessionContext.PreBatchKeyConsistentReadCallback when TryReadLock() on the 'inProgress' lock fails. This is the pre-read initialization for a batch of keys: it checks the consistency-manager version and caches key hashes. The read lock cannot be acquired because a writer (Dispose) currently holds it.

Source

Thrown at libs/server/AOF/ReadConsistency/ReplicaReadSessionContext.cs:201

                throw new GarnetException($"Failed to acquire inProgress lock at {nameof(PostSingleKeyConsistentReadCallback)}");
            try
            {
                appendOnlyFile.readConsistencyManager.PostSingleKeyConsistentRead(ref replicaReadContext);
            }
            finally
            {
                inProgress.ReadUnlock();
            }
        }

        /// <summary>
        /// Initialize context for read key batch.
        /// </summary>
        /// <param name="parameters"></param>
        public void PreBatchKeyConsistentReadCallback(ReadOnlySpan<PinnedSpanByte> parameters)
        {
            if (!inProgress.TryReadLock())
                throw new GarnetException($"Failed to acquire inProgress lock at {nameof(PreBatchKeyConsistentReadCallback)}");
            try
            {
                var keyCount = parameters.Length;
                var consistencyManager = appendOnlyFile.readConsistencyManager;
                // First check if version of consistency manager has changed
                appendOnlyFile.readConsistencyManager.CheckConsistencyManagerVersion(ref replicaReadContext);

                // Allocate array to cache key hashes for batch read
                if (keyHashCache == null || keyCount > keyHashCache.Length)
                    ExpandKeyHashCache(keyCount);
                else if ((keyCount << 2) < keyHashCache.Length)
                    ShrinkKeyHashCache(keyCount);

                // NOTE: this context is a copy used to emulate standalone reads.
                // The actual update of the session max will happen after the read succeeds.
                batchReadContext = replicaReadContext;
                for (var i = 0; i < parameters.Length; i++)
                {

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Verify session liveness before issuing the batch read.
  2. Catch GarnetException and return an error to the client (e.g. session closed).
  3. Ensure dispose waits for all queued read callbacks to drain.
  4. Add a disposed-flag guard at the start of the batch-read entry point.

Example fix

// before
session.PreBatchKeyConsistentReadCallback(parameters);

// after
if (session.IsDisposed) return BatchReadResult.SessionClosed;
try { session.PreBatchKeyConsistentReadCallback(parameters); }
catch (GarnetException) { return BatchReadResult.SessionClosed; }
Defensive patterns

Strategy: try-catch

Validate before calling

if (session.IsDisposed) return BatchReadResult.SessionClosed;
session.PreBatchKeyConsistentReadCallback(parameters);

Try / catch

try { session.PreBatchKeyConsistentReadCallback(parameters); }
catch (GarnetException ex) when (ex.Message.Contains("inProgress lock"))
{ return BatchReadResult.SessionClosed; }

Prevention

When it happens

Trigger: A batch consistent read is initiated on a session that is concurrently being disposed, or a write lock is held due to re-entrancy. The non-blocking TryReadLock returns false and the method throws.

Common situations: Connection close / session teardown racing with a batch read request; a cancellation path disposing the session while the batch read callback is queued; a bug calling the batch read on a disposed session.

Related errors


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