microsoft/FASTER · error · FasterException
log has already been closed
Error message
log has already been closed
What it means
A commit was requested (CommitAsync path in FasterLog.cs:2733) after the log has been closed: the internal commitNum has been set to long.MaxValue during close/shutdown. The library throws rather than silently committing to a dead log.
Solutions
- Ensure all CommitAsync calls complete before disposing: await outstanding commits, then Dispose.
- Guard commit calls with the log's lifecycle (check disposed/closed flag or a CancellationToken that is cancelled on shutdown).
- Serialize shutdown: stop producers, drain, then dispose in one place rather than concurrently.
- If it appears without explicit Dispose, look for an earlier exception that closed the log and handle that root cause.
Example fix
// before log.Dispose(); await producerTask; // producer may still CommitAsync -> throws // after cts.Cancel(); // signal producers to stop await producerTask; // drain in-flight commits log.Dispose();
Defensive patterns
Strategy: try-catch
Validate before calling
if (logDisposed) return; // track disposal in your wrapper
Try / catch
try { await log.CommitAsync(); } catch (FasterException ex) when (ex.Message == "log has already been closed") { /* shutdown race: ignore */ } Prevention
- Cancel producers and drain commits before Dispose
- Single owner thread handles shutdown
- Guard with CancellationToken tied to shutdown
When it happens
Trigger: Calling CommitAsync after Dispose/Close on FasterLog, or racing a commit with shutdown (background commit task firing during Dispose).
Common situations: Application shutdown ordering: a producer task still committing while another thread disposes the log; failing to await in-flight commits before calling Dispose; restart-after-checkpoint reusing a disposed instance.
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
- Cannot scan disposed log instance
- requested commit num is not available
- Cannot commit in read-only mode
- Fast forwarding a commit is only allowed when no cookie…
- Already recovered until address
AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15).
Data as JSON: /api/errors/498157ae99df079c.
Report an issue: GitHub.
Appendix: source
Thrown at cs/src/core/FasterLog/FasterLog.cs:2733
};
info.SnapshotIterators(PersistedIterators);
var commitRequired = ShouldCommmitMetadata(ref info) || (commitCoveredAddress < TailAddress);
// Only apply commit policy if not a strong commit
if (fastForwardAllowed && !commitPolicy.AdmitCommit(TailAddress, commitRequired))
return false;
// This critical section serializes commit record creation / commit content generation and ensures that the
// long address are sorted in outstandingCommitRecords. Ok because we do not expect heavy contention on the
// commit code path
lock (ongoingCommitRequests)
{
if (commitCoveredAddress == TailAddress && !commitRequired)
// Nothing to commit if no metadata update and no new entries
return false;
if (commitNum == long.MaxValue)
{
// log has been closed, throw an exception
throw new FasterException("log has already been closed");
}
// Make sure we will not be allowed to back out of a commit if AdmitCommit returns true, as the commit policy
// may need to update internal logic for every true response. We might waste some commit nums if commit
// policy filters out a lot of commits, but that's fine.
if (proposedCommitNum == -1)
info.CommitNum = actualCommitNum = ++commitNum;
else if (proposedCommitNum > commitNum)
info.CommitNum = actualCommitNum = commitNum = proposedCommitNum;
else
// Invalid commit num
return false;
// Normally --- only need commit records if fast committing.
if (fastCommitMode)
{
// Ok to retry in critical section, any concurrently invoked commit would block, but cannot progress
// anyways if no record can be enqueuedView on GitHub (pinned to 321d872eab)