{"record":{"id":"08ac17c35e89cb46","repo":"microsoft/FASTER","slug":"page-read-from-storage-failed-skipping-page-inner-exception","errorCode":null,"errorMessage":"Page read from storage failed, skipping page. Inner exception: ","messagePattern":"Page read from storage failed, skipping page\\. Inner exception: ","errorType":"exception","errorClass":"FasterException","httpStatus":null,"severity":"error","filePath":"cs/src/core/Allocator/ScanIteratorBase.cs","lineNumber":226,"sourceCode":"        }\n\n        internal abstract void AsyncReadPagesFromDeviceToFrame<TContext>(long readPageStart, int numPages, long untilAddress, TContext context, out CountdownEvent completed, long devicePageOffset = 0, IDevice device = null, IDevice objectLogDevice = null, CancellationTokenSource cts = null);\n\n        private bool WaitForFrameLoad(long currentAddress, long currentFrame)\n        {\n            if (loaded[currentFrame].IsSet) return false;\n\n            try\n            {\n                epoch?.Suspend();\n                loaded[currentFrame].Wait(loadedCancel[currentFrame].Token); // Ensure we have completed ongoing load\n            }\n            catch (Exception e)\n            {\n                loadedPage[currentFrame] = -1;\n                loadedCancel[currentFrame] = new CancellationTokenSource();\n                Utility.MonotonicUpdate(ref nextAddress, (1 + (currentAddress >> logPageSizeBits)) << logPageSizeBits, out _);\n                throw new FasterException(\"Page read from storage failed, skipping page. Inner exception: \" + e.ToString());\n            }\n            finally\n            {\n                epoch?.Resume();\n            }\n            return true;\n        }\n\n        /// <summary>\n        /// Dispose iterator\n        /// </summary>\n        public virtual void Dispose()\n        {\n            if (loaded != null)\n            {\n                // Wait for ongoing reads to complete/fail\n                for (int i = 0; i < frameSize; i++)\n                {","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/microsoft/FASTER/blob/321d872eabda6a0345c8bd76419f89723ed864ae/cs/src/core/Allocator/ScanIteratorBase.cs#L208-L244","documentation":"FASTER's scan iterator loads log pages from disk asynchronously; when the page read or its continuation throws, WaitForFrameLoad catches it, marks the page as not loaded, advances the iterator to the next page boundary, and rethrows this wrapped FasterException. The library throws it so scanning code knows a specific page could not be read from storage rather than the whole scan silently stalling. The original exception text is appended as 'Inner exception: <full ToString()>'.","triggerScenarios":"Calling ScanIteratorBase.GetNext/BufferAndLoad when the underlying read from the IDevice (e.g. a LocalStorageDevice or AzureStorageDevice) fails during WaitForFrameLoad: corrupted or truncated log file, page beyond the file's end, device/credentials failure, or a checkpoint restore pointing at a deleted epoch file.","commonSituations":"Scanning a FASTER hybrid log whose backing files were deleted or truncated by another process; reading a log copied without its tail; transient cloud-storage (Azure blob) IO failures or expired SAS credentials mid-scan; disk full or hardware errors during a long scan.","solutions":["Inspect the appended inner exception text to find the real IO failure and fix its cause (file present, credentials valid, disk space).","Verify the log directory/files are intact and the iterator's beginAddress matches the checkpoint the log was taken at.","Retry the scan after the transient storage failure clears; the iterator already advanced nextAddress past the bad page.","Use a fault-tolerant storage device wrapper (e.g. ReadCacheDevice/renumbering or graceful-failover device factory) if you want reads of missing pages to be tolerated.","If the log is known-healthy, report the underlying device exception; do not swallow it, as data in that page is unavailable."],"exampleFix":"// before: scan assumes every page is readable\nusing var iter = fkv.Log.Scan(beginAddress, long.MaxValue, (out RecordInfo info) => info.Valid, scanBufferingMode: ScanBufferingMode.DoublePageBuffering);\nwhile (iter.GetNext(out RecordInfo info)) { ... }\n// after: catch page-read failures and skip/stop gracefully\ntry {\n    using var iter = fkv.Log.Scan(beginAddress, long.MaxValue, (out RecordInfo info) => info.Valid, ScanBufferingMode.DoublePageBuffering);\n    while (iter.GetNext(out RecordInfo info)) { ... }\n} catch (FasterException ex) when (ex.Message.StartsWith(\"Page read from storage failed\")) {\n    logger.LogError(ex, \"Scan hit unreadable page; aborting or restarting scan after beginAddress advanced\");\n}","handlingStrategy":"try-catch","validationCode":"// before scanning, confirm the backing files/checkpoint are reachable\nif (!Directory.Exists(logDir) || !File.Exists(Path.Combine(logDir, \"checkpoint\")))\n    throw new InvalidOperationException(\"FASTER log storage missing; cannot start scan\");\n// and confirm the start address is within the log\nif (startAddress < log.BeginAddress || startAddress > log.TailAddress)\n    throw new InvalidOperationException($\"Scan address {startAddress} outside [{log.BeginAddress},{log.TailAddress}]\");","typeGuard":null,"tryCatchPattern":"try {\n    while (iter.GetNext(out RecordInfo info)) { /* process */ }\n} catch (FasterException ex) when (ex.Message.Contains(\"Page read from storage failed\")) {\n    logger.LogError(ex, \"Page read failed during scan at/after address {Address}; inspect inner exception\", iter.NextAddress);\n    // resume scan from iter.NextAddress or fail the job\n}","preventionTips":["Always log the full exception text after 'Inner exception:' — the real cause is there","Use durable storage device wrappers or retry policies for cloud-backed devices","Validate checkpoint/log file integrity before long scans","Alert on disk-space and file-deletion events in the log directory","Keep iterator addresses at or above log.BeginAddress when resuming"],"tags":["io","storage","scan-iterator","faster-log"],"backgroundTag":"file-read-failed","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"}