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
- Ensure AcquireLockable (BeginLockable) is called once before any EndLockable call on the session.
- Track lockable state in application code (a bool) and skip EndLockable when not acquired.
- Fix unbalanced begin/end pairs - one BeginLockable per EndLockable, in matched pairs.
- 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
- Track a bool flag per session mirroring Begin/EndLockable state
- Only call EndLockable in the same scope that called BeginLockable
- Guard shared teardown/cleanup paths against double execution
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
- BeginLockable cannot be called twice (call EndLockable…
- EndLockable called with locks held
- Cannot scan disposed log instance
- Attempt to lock with unknown LockType
- Out of order message within session
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)