microsoft/FASTER · error · FasterException
BeginLockable cannot be called twice (call EndLockable…
Error message
BeginLockable cannot be called twice (call EndLockable first)
What it means
CheckIsNotAcquiredLockable throws this FasterException when AcquireLockable (BeginLockable) is called on a session that is already in the lockable-acquired state. A session supports only one outstanding BeginLockable; the caller must EndLockable first before beginning again.
Solutions
- Ensure each AcquireLockable is paired with a ReleaseLockable before the next AcquireLockable.
- Do not share a single ClientSession across threads that each attempt BeginLockable; give each thread its own session.
- Guard acquisition with a flag or check so re-entrant calls are skipped instead of re-acquired.
- Fix retry logic to release the lockable state (EndLockable) before re-attempting AcquireLockable.
Example fix
// before
session.AcquireLockable();
session.AcquireLockable(); // throws - already acquired
// after
if (!sessionAcquired)
{
session.AcquireLockable();
sessionAcquired = true;
} Defensive patterns
Strategy: validation
Validate before calling
if (sessionLockableAcquired) throw new InvalidOperationException("EndLockable must be called before AcquireLockable again"); Try / catch
try
{
session.AcquireLockable();
}
catch (FasterException)
{
// already acquired; release first or use a separate session
} Prevention
- Never share a ClientSession across threads performing locking
- Pair every AcquireLockable with a ReleaseLockable before re-acquiring
- In retry loops, always EndLockable before re-beginning
When it happens
Trigger: Calling AcquireLockable twice without an intervening ReleaseLockable/EndLockable - e.g. re-entering a locking region on the same ClientSession while isAcquiredLockable is still true.
Common situations: Nested or re-entrant locking logic on the same session; concurrent threads sharing one ClientSession and both calling AcquireLockable; retry loops that re-acquire without releasing after a failed operation.
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
- Lockable method call when BeginLockable has not been called
- Unexpected sealed buffer found
- Invalid release by non-owner thread
- EndLockable called with locks held
- LockableUnsafeContext requires
AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15).
Data as JSON: /api/errors/59aad66da3d9fd10.
Report an issue: GitHub.
Appendix: source
Thrown at cs/src/core/ClientSession/ClientSession.cs:103
}
[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);
if (fht.LockTable.IsEnabled)
{
this.lContext = new(this);
this.luContext = new(this);
}
View on GitHub (pinned to 321d872eab)