{"record":{"id":"191e292346bf9b96","repo":"microsoft/FASTER","slug":"cannot-use-scanuncommitted-with-read-only-fasterlog","errorCode":null,"errorMessage":"Cannot use scanUncommitted with read-only FasterLog","messagePattern":"Cannot use scanUncommitted with read-only FasterLog","errorType":"exception","errorClass":"FasterException","httpStatus":null,"severity":"error","filePath":"cs/src/core/FasterLog/FasterLog.cs","lineNumber":1820,"sourceCode":"        /// </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))\n                    logger?.LogDebug(\"Iterator name exists, overwriting\");\n                PersistedIterators[name] = iter;","sourceCodeStart":1802,"sourceCodeEnd":1838,"githubUrl":"https://github.com/microsoft/FASTER/blob/321d872eabda6a0345c8bd76419f89723ed864ae/cs/src/core/FasterLog/FasterLog.cs#L1802-L1838","documentation":"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.","triggerScenarios":"Calling log.Scan(begin, end, name, scanUncommitted: true) (or the iterator constructor variant) on a FasterLog opened with readOnlyMode.","commonSituations":"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.","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."],"exampleFix":"// before\nusing var iter = readOnlyLog.Scan(begin, end, null, scanUncommitted: true);\n// after\nusing var iter = readOnlyLog.Scan(begin, readOnlyLog.TailAddress, null); // committed only","handlingStrategy":"validation","validationCode":"void GuardScanUncommitted(FasterLog log, bool scanUncommitted)\n{\n    if (scanUncommitted && log.ReadOnlyMode)\n        throw new InvalidOperationException(\"scanUncommitted unsupported on read-only logs\");\n}","typeGuard":null,"tryCatchPattern":"try { iter = log.Scan(begin, end, null, scanUncommitted); }\ncatch (FasterException ex) when (ex.Message == \"Cannot use scanUncommitted with read-only FasterLog\")\n{\n    iter = log.Scan(begin, end, null); // committed data only\n}","preventionTips":["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."],"tags":["fasterlog","iterator","read-only","scan"],"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"}