{"record":{"id":"6fec28ea67196fd4","repo":"microsoft/FASTER","slug":"cannot-use-named-iterators-with-read-only-fasterlog","errorCode":null,"errorMessage":"Cannot use named iterators with read-only FasterLog","messagePattern":"Cannot use named iterators with read-only FasterLog","errorType":"exception","errorClass":"FasterException","httpStatus":null,"severity":"error","filePath":"cs/src/core/FasterLog/FasterLog.cs","lineNumber":1818,"sourceCode":"        /// <summary>\n        /// Pull-based iterator interface for scanning FASTER log\n        /// </summary>\n        /// <param name=\"beginAddress\">Begin address for scan.</param>\n        /// <param name=\"endAddress\">End address for scan (or long.MaxValue for tailing).</param>\n        /// <param name=\"name\">Name of iterator, if we need to persist/recover it (default null - do not persist).</param>\n        /// <param name=\"recover\">Whether to recover named iterator from latest commit (if exists). If false, iterator starts from beginAddress.</param>\n        /// <param name=\"scanBufferingMode\">Use single or double buffering</param>\n        /// <param name=\"scanUncommitted\">Whether we scan uncommitted data</param>\n        /// <param name=\"logger\"></param>\n        /// <returns></returns>\n        public FasterLogScanIterator Scan(long beginAddress, long endAddress, string name = null, bool recover = true, ScanBufferingMode scanBufferingMode = ScanBufferingMode.DoublePageBuffering, bool scanUncommitted = false, ILogger logger = null)\n        {\n            if (readOnlyMode)\n            {\n                scanBufferingMode = ScanBufferingMode.SinglePageBuffering;\n\n                if (name != null)\n                    throw new FasterException(\"Cannot use named iterators with read-only FasterLog\");\n                if (scanUncommitted)\n                    throw new FasterException(\"Cannot use scanUncommitted with read-only FasterLog\");\n            }\n\n            if (scanUncommitted && !AutoRefreshSafeTailAddress)\n                throw new FasterException(\"Cannot use scanUncommitted without setting AutoRefreshSafeTailAddress to true in FasterLog settings\");\n\n            FasterLogScanIterator iter;\n            if (recover && name != null && RecoveredIterators != null && RecoveredIterators.ContainsKey(name))\n                iter = new FasterLogScanIterator(this, allocator, RecoveredIterators[name], endAddress, getMemory, scanBufferingMode, epoch, headerSize, name, scanUncommitted, logger: logger);\n            else\n                iter = new FasterLogScanIterator(this, allocator, beginAddress, endAddress, getMemory, scanBufferingMode, epoch, headerSize, name, scanUncommitted, logger: logger);\n\n            if (name != null)\n            {\n                if (name.Length > 20)\n                    throw new FasterException(\"Max length of iterator name is 20 characters\");\n                if (PersistedIterators.ContainsKey(name))","sourceCodeStart":1800,"sourceCodeEnd":1836,"githubUrl":"https://github.com/microsoft/FASTER/blob/321d872eabda6a0345c8bd76419f89723ed864ae/cs/src/core/FasterLog/FasterLog.cs#L1800-L1836","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nusing var iter = readOnlyLog.Scan(begin, end, \"my-iterator\"); // throws on read-only log\n// after\nusing var iter = readOnlyLog.Scan(begin, end, null);","handlingStrategy":"validation","validationCode":"void GuardScan(FasterLog log, string name)\n{\n    if (name != null && log.ReadOnlyMode)\n        throw new InvalidOperationException(\"Named iterators unsupported on read-only logs; pass null name\");\n}","typeGuard":null,"tryCatchPattern":"try { iter = log.Scan(begin, end, name); }\ncatch (FasterException ex) when (ex.Message == \"Cannot use named iterators with read-only FasterLog\")\n{\n    iter = log.Scan(begin, end, null); // fall back to unnamed iterator\n}","preventionTips":["Use named iterators only on writable primary logs.","Persist replay positions externally when scanning read-only copies.","Check readOnlyMode before building shared scan helpers."],"tags":["fasterlog","iterator","read-only"],"backgroundTag":"unsupported-operation","analyzedSha":"321d872eabda6a0345c8bd76419f89723ed864ae","analyzedAt":"2026-09-15T22:18:00.693Z","contentChangedAt":"2026-09-15T22:18:00.693Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}