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

  1. Use an unnamed iterator: pass null for the name in Scan().
  2. Track replay position yourself (store the recovered iterator's address externally).
  3. 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

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


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)