microsoft/garnet · error · GarnetException
Checkpoint history unavailable, need full checkpoint for {en
Error message
Checkpoint history unavailable, need full checkpoint for {entry} What it means
Thrown by CheckpointStore.AddCheckpointEntry when adding a non-full (incremental) checkpoint but the history list is empty (tail == null). Incremental checkpoints reuse the previous checkpoint's storeIndexToken, so with no prior checkpoint there is nothing to inherit; a full checkpoint is required first to seed the history.
Source
Thrown at libs/cluster/Server/Replication/CheckpointStore.cs:122
ckptManager.DeleteIndexCheckpoint(toDeleteIndexToken);
}
}
}
}
/// <summary>
/// Add new checkpoint entry to in memory list.
/// Assume that addition of new entries executes at completion of a checkpoint.
/// Since there can be not concurrent checkpoints this method is not thread safe.
/// </summary>
/// <param name="entry"></param>
/// <param name="fullCheckpoint"></param>
public void AddCheckpointEntry(CheckpointEntry entry, bool fullCheckpoint = false)
{
// If not full checkpoint index checkpoint will be the one of the previous checkpoint
if (!fullCheckpoint)
{
var lastEntry = tail ?? throw new GarnetException($"Checkpoint history unavailable, need full checkpoint for {entry}");
entry.metadata.storeIndexToken = lastEntry.metadata.storeIndexToken;
}
_ = ValidateCheckpointEntry(entry);
if (tail == null)
head = tail = entry;
else
{
// We don't have multiple writers because this method is called under the CheckpointLock
// So it is safe to update in-place.
tail.next = entry;
tail = tail.next;
}
logger?.LogCheckpointEntry(LogLevel.Trace, nameof(AddCheckpointEntry), entry);
if (safelyRemoveOutdated)View on GitHub (pinned to 951b0fc683)
Solutions
- Ensure the first checkpoint after store creation (or after history reset) is taken as a full checkpoint (fullCheckpoint: true).
- Audit the checkpoint-scheduling logic so an empty history always forces a full checkpoint.
- If the condition is recoverable, automatically promote to a full checkpoint instead of throwing.
Example fix
// before store.AddCheckpointEntry(entry, fullCheckpoint: false); // after var isFull = store.IsEmpty || requestedFull; store.AddCheckpointEntry(entry, fullCheckpoint: isFull);
Defensive patterns
Strategy: validation
Validate before calling
// Force a full checkpoint when history is empty
bool isFull = requestedFull || storeHistoryIsEmpty;
if (!isFull && storeHistoryIsEmpty)
throw new InvalidOperationException("First checkpoint must be a full checkpoint");
store.AddCheckpointEntry(entry, fullCheckpoint: isFull); Prevention
- Guarantee the first checkpoint after store creation or history reset is full.
- Have the checkpoint scheduler force full when the history list is empty.
- Consider auto-promoting to full instead of throwing for recoverable cases.
When it happens
Trigger: Calling AddCheckpointEntry(entry, fullCheckpoint: false) before any full checkpoint has ever been recorded, so tail is null.
Common situations: First-ever checkpoint taken with the full-checkpoint flag accidentally false; history wiped/recreated and the next checkpoint assumed incremental; a startup race where the store is empty but an incremental is queued.
Related errors
- Option {fileType} not supported
- Failed to validate main store metadata at insertion
- RetrieveCheckpointFile: unexpected state{retStateType}
- invalid metadata length: {hlri.cookie.Length} < 4
- invalid metadata length: {hlri.cookie.Length} < 12
AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13).
Data as JSON: /api/errors/66f81c32574d233d.
Report an issue: GitHub.