microsoft/FASTER · error · FasterException

Lockable method call when BeginLockable has not been called

Error message

Lockable method call when BeginLockable has not been called

What it means

CheckIsAcquiredLockable throws this FasterException when a lockable method (e.g. ReleaseLockable/EndLockable) is invoked before BeginLockable (AcquireLockable) established the session's lockable state. The isAcquiredLockable flag must be set by BeginLockable before any lockable operation is legal.

Solutions

  1. Ensure AcquireLockable (BeginLockable) is called once before any EndLockable call on the session.
  2. Track lockable state in application code (a bool) and skip EndLockable when not acquired.
  3. Fix unbalanced begin/end pairs - one BeginLockable per EndLockable, in matched pairs.
  4. Check exception paths: if the operation that should have called BeginLockable failed, don't run the release.

Example fix

// before
session.ReleaseLockable(); // throws if BeginLockable never ran
// after
if (sessionAcquired)
{
    session.ReleaseLockable();
    sessionAcquired = false;
}
Defensive patterns

Strategy: validation

Validate before calling

if (!sessionLockableAcquired) throw new InvalidOperationException("BeginLockable must be called before EndLockable");

Try / catch

try
{
    session.ReleaseLockable();
}
catch (FasterException)
{
    // session was never acquired-lockable; skip teardown
}

Prevention

When it happens

Trigger: Calling EndLockable/ReleaseLockable on a session on which AcquireLockable was never called, or calling it twice after the first EndLockable already cleared isAcquiredLockable.

Common situations: Lifecycle mistakes where EndLockable runs on a session just created or already finished; double-teardown of a session (two cleanup paths each calling EndLockable); copy/pasted cleanup code that assumes BeginLockable was executed elsewhere.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15). Data as JSON: /api/errors/1f10d2675fdfceb6. Report an issue: GitHub.

Appendix: source

Thrown at cs/src/core/ClientSession/ClientSession.cs:97

        internal void ReleaseLockable()
        {
            CheckIsAcquiredLockable();
            if (TotalLockCount > 0)
                throw new FasterException($"EndLockable called with locks held: {sharedLockCount} shared locks, {exclusiveLockCount} exclusive locks");
            InternalReleaseLockable();
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private void InternalReleaseLockable()
        {
            isAcquiredLockable = false;
            fht.DecrementNumLockingSessions();
        }

        internal void CheckIsAcquiredLockable()
        {
            if (!isAcquiredLockable)
                throw new FasterException("Lockable method call when BeginLockable has not been called");
        }

        void CheckIsNotAcquiredLockable()
        {
            if (isAcquiredLockable)
                throw new FasterException("BeginLockable cannot be called twice (call EndLockable first)");
        }

        internal ClientSession(
            FasterKV<Key, Value> fht,
            FasterKV<Key, Value>.FasterExecutionContext<Input, Output, Context> ctx,
            Functions functions,
            SessionVariableLengthStructSettings<Value, Input> sessionVariableLengthStructSettings,
            ILoggerFactory loggerFactory = null)
        {
            this.bContext = new(this);
            this.uContext = new(this);

View on GitHub (pinned to 321d872eab)