microsoft/garnet · error · GarnetException

Failed to acquire inProgress lock at {nameof(PreSingleKeyCon

Error message

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

What it means

Thrown by ReplicaReadSessionContext.PreSingleKeyConsistentRead when the internal SingleWriterMultiReaderLock 'inProgress' cannot be acquired for reading via TryReadLock(). TryReadLock fails when a writer currently holds the lock (e.g. Dispose is in progress, which takes a write lock). This is a session-lifecycle / concurrency error, not a data error.

Source

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

        public void Dispose()
        {
            consistentReadCts.Cancel();
            inProgress.WriteLock();
            consistentReadCts.Dispose();
            // batchReadContext shares the same waiter reference, so dispose it once here.
            replicaReadContext.waiter?.Dispose();
        }

        /// <summary>
        /// Freshness check before actual read for a single key
        /// </summary>
        /// <param name="hash"></param>
        /// <exception cref="GarnetException"></exception>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void PreSingleKeyConsistentRead(long hash)
        {
            if (!inProgress.TryReadLock())
                throw new GarnetException($"Failed to acquire inProgress lock at {nameof(PreSingleKeyConsistentRead)}");
            try
            {
                appendOnlyFile.readConsistencyManager.PreSingleKeyConsistentRead(hash & long.MaxValue, ref replicaReadContext, readTimeout, consistentReadCts.Token);
            }
            finally
            {
                inProgress.ReadUnlock();
            }
        }

        /// <summary>
        /// Post read update maximum sequence number for a single key.
        /// </summary>
        /// <exception cref="GarnetException"></exception>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void PostSingleKeyConsistentReadCallback()
        {
            if (!inProgress.TryReadLock())

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Ensure the session is not disposed while reads are in flight — gate reads on session lifetime.
  2. Guard the read call with a disposed-flag check before invoking PreSingleKeyConsistentRead.
  3. Catch GarnetException at the call site and convert it to a client-readable error (e.g. 'session disposed').
  4. Review shutdown ordering: complete pending reads before disposing the replica read session.

Example fix

// before
session.PreSingleKeyConsistentRead(hash); // may throw if disposing

// after
if (session.IsDisposed) return ReadResult.SessionClosed;
try { session.PreSingleKeyConsistentRead(hash); }
catch (GarnetException) { return ReadResult.SessionClosed; }
Defensive patterns

Strategy: try-catch

Validate before calling

// Guard against calling read methods on a disposing session
if (session.IsDisposed) return ReadResult.SessionClosed;
session.PreSingleKeyConsistentRead(hash);

Try / catch

try { session.PreSingleKeyConsistentRead(hash); }
catch (GarnetException ex) when (ex.Message.Contains("inProgress lock"))
{ /* session is disposing; abort the read gracefully */ return ReadResult.SessionClosed; }

Prevention

When it happens

Trigger: A consistent read is attempted on a replica read session that is concurrently being disposed (Dispose calls inProgress.WriteLock), or re-entrant access while a write lock is held. The read-path lock is non-blocking (Try, not Wait), so it throws immediately rather than waiting.

Common situations: A session is being torn down while in-flight reads are still active; a race between request cancellation/dispose and the read callback; a programming bug where PreSingleKeyConsistentRead is called after Dispose.

Related errors


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