microsoft/FASTER · error · FasterException
Cannot use scanUncommitted with read-only FasterLog
Error message
Cannot use scanUncommitted with read-only FasterLog
What it means
A read-only FasterLog cannot scan uncommitted regions: with readOnlyMode the tail is fixed and cannot be refreshed, so scanUncommitted=true is rejected with FasterException. Uncommitted-area scanning also requires AutoRefreshSafeTailAddress semantics, which read-only logs do not support in combination.
Solutions
- Pass scanUncommitted: false and scan only committed data.
- Open the log on a writable device (non-read-only mode) if tail-following is required.
- Set AutoRefreshSafeTailAddress=true on a writable log and use scanUncommitted there instead.
Example fix
// before using var iter = readOnlyLog.Scan(begin, end, null, scanUncommitted: true); // after using var iter = readOnlyLog.Scan(begin, readOnlyLog.TailAddress, null); // committed only
Defensive patterns
Strategy: validation
Validate before calling
void GuardScanUncommitted(FasterLog log, bool scanUncommitted)
{
if (scanUncommitted && log.ReadOnlyMode)
throw new InvalidOperationException("scanUncommitted unsupported on read-only logs");
} Try / catch
try { iter = log.Scan(begin, end, null, scanUncommitted); }
catch (FasterException ex) when (ex.Message == "Cannot use scanUncommitted with read-only FasterLog")
{
iter = log.Scan(begin, end, null); // committed data only
} Prevention
- Default scanUncommitted=false in shared iterator helpers.
- On read-only replicas, scan only committed addresses up to the snapshot tail.
- Enable AutoRefreshSafeTailAddress only on writable logs for tail-following scenarios.
When it happens
Trigger: Calling log.Scan(begin, end, name, scanUncommitted: true) (or the iterator constructor variant) on a FasterLog opened with readOnlyMode.
Common situations: Following the live tail on a read-only replica/archive; porting tail-follow code from a writable log to a read-only snapshot; enabling scanUncommitted by default in shared iterator helpers.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Cannot use named iterators with read-only FasterLog
- Iterator address is less than log HeadAddress in…
- Cannot use scanUncommitted without setting…
- Max length of iterator name is 20 characters
- This method can only be used with a read-only FasterLog…
AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15).
Data as JSON: /api/errors/191e292346bf9b96.
Report an issue: GitHub.
Appendix: source
Thrown at cs/src/core/FasterLog/FasterLog.cs:1820
/// </summary>
/// <param name="beginAddress">Begin address for scan.</param>
/// <param name="endAddress">End address for scan (or long.MaxValue for tailing).</param>
/// <param name="name">Name of iterator, if we need to persist/recover it (default null - do not persist).</param>
/// <param name="recover">Whether to recover named iterator from latest commit (if exists). If false, iterator starts from beginAddress.</param>
/// <param name="scanBufferingMode">Use single or double buffering</param>
/// <param name="scanUncommitted">Whether we scan uncommitted data</param>
/// <param name="logger"></param>
/// <returns></returns>
public FasterLogScanIterator Scan(long beginAddress, long endAddress, string name = null, bool recover = true, ScanBufferingMode scanBufferingMode = ScanBufferingMode.DoublePageBuffering, bool scanUncommitted = false, ILogger logger = null)
{
if (readOnlyMode)
{
scanBufferingMode = ScanBufferingMode.SinglePageBuffering;
if (name != null)
throw new FasterException("Cannot use named iterators with read-only FasterLog");
if (scanUncommitted)
throw new FasterException("Cannot use scanUncommitted with read-only FasterLog");
}
if (scanUncommitted && !AutoRefreshSafeTailAddress)
throw new FasterException("Cannot use scanUncommitted without setting AutoRefreshSafeTailAddress to true in FasterLog settings");
FasterLogScanIterator iter;
if (recover && name != null && RecoveredIterators != null && RecoveredIterators.ContainsKey(name))
iter = new FasterLogScanIterator(this, allocator, RecoveredIterators[name], endAddress, getMemory, scanBufferingMode, epoch, headerSize, name, scanUncommitted, logger: logger);
else
iter = new FasterLogScanIterator(this, allocator, beginAddress, endAddress, getMemory, scanBufferingMode, epoch, headerSize, name, scanUncommitted, logger: logger);
if (name != null)
{
if (name.Length > 20)
throw new FasterException("Max length of iterator name is 20 characters");
if (PersistedIterators.ContainsKey(name))
logger?.LogDebug("Iterator name exists, overwriting");
PersistedIterators[name] = iter;View on GitHub (pinned to 321d872eab)