microsoft/FASTER · error · FasterException
Cannot use named iterators with read-only FasterLog
Error message
Cannot use named iterators with read-only FasterLog
What it means
FasterLogScanIterator's setup validates iterator options against the log's mode. A read-only FasterLog (opened on a read-only device/device factory) cannot register named iterators because named iterators persist their position by committing iterator names to the log, which requires writes. Attempting Scan(name != null) on a read-only log throws FasterException.
Solutions
- Use an unnamed iterator: pass null for the name in Scan().
- Track replay position yourself (store the recovered iterator's address externally).
- Open the log on a writable device if named iterators are truly needed.
Example fix
// before using var iter = readOnlyLog.Scan(begin, end, "my-iterator"); // throws on read-only log // after using var iter = readOnlyLog.Scan(begin, end, null);
Defensive patterns
Strategy: validation
Validate before calling
void GuardScan(FasterLog log, string name)
{
if (name != null && log.ReadOnlyMode)
throw new InvalidOperationException("Named iterators unsupported on read-only logs; pass null name");
} Try / catch
try { iter = log.Scan(begin, end, name); }
catch (FasterException ex) when (ex.Message == "Cannot use named iterators with read-only FasterLog")
{
iter = log.Scan(begin, end, null); // fall back to unnamed iterator
} Prevention
- Use named iterators only on writable primary logs.
- Persist replay positions externally when scanning read-only copies.
- Check readOnlyMode before building shared scan helpers.
When it happens
Trigger: Creating a scan iterator with a non-null name on a FasterLog constructed with readOnlyMode (e.g., logDataDevice opened read-only) - i.e., calling log.Scan(begin, end, name).
Common situations: Replaying a log shipped/read-only on a replica or archived device; reusing scan code that names iterators on a writable primary against a read-only copy; config mistakes mounting the log device read-only.
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 scanUncommitted with read-only FasterLog
- Cannot use scanUncommitted without setting…
- Max length of iterator name is 20 characters
- This method can only be used with a read-only FasterLog…
- Cannot commit in read-only mode
AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15).
Data as JSON: /api/errors/6fec28ea67196fd4.
Report an issue: GitHub.
Appendix: source
Thrown at cs/src/core/FasterLog/FasterLog.cs:1818
/// <summary>
/// Pull-based iterator interface for scanning FASTER log
/// </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))View on GitHub (pinned to 321d872eab)