{"record":{"id":"9352a48ac8046b17","repo":"microsoft/FASTER","slug":"error-reading-page-pageindex-from-device","errorCode":null,"errorMessage":"Error reading page {pageIndex} from device","messagePattern":"Error reading page (.+?) from device","errorType":"exception","errorClass":"FasterException","httpStatus":null,"severity":"error","filePath":"cs/src/core/Index/Recovery/Recovery.cs","lineNumber":72,"sourceCode":"        internal void SignalRead(int pageIndex)\n        {\n            this.readStatus[pageIndex] = ReadStatus.Done;\n            this.readSemaphore.Release();\n        }\n\n        internal void SignalReadError(int pageIndex)\n        {\n            this.readStatus[pageIndex] = ReadStatus.Error;\n            this.readSemaphore.Release();\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        internal void WaitRead(int pageIndex)\n        {\n            while (this.readStatus[pageIndex] == ReadStatus.Pending)\n                this.readSemaphore.Wait();\n            if (this.readStatus[pageIndex] == ReadStatus.Error)\n                throw new FasterException($\"Error reading page {pageIndex} from device\");\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        internal async ValueTask WaitReadAsync(int pageIndex, CancellationToken cancellationToken)\n        {\n            while (this.readStatus[pageIndex] == ReadStatus.Pending)\n                await this.readSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);\n            if (this.readStatus[pageIndex] == ReadStatus.Error)\n                throw new FasterException($\"Error reading page {pageIndex} from device\");\n        }\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        internal void SignalFlushed(int pageIndex)\n        {\n            this.flushStatus[pageIndex] = FlushStatus.Done;\n            this.flushSemaphore.Release();\n        }\n","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/microsoft/FASTER/blob/321d872eabda6a0345c8bd76419f89723ed864ae/cs/src/core/Index/Recovery/Recovery.cs#L54-L90","documentation":"Recovery.WaitRead blocks on a semaphore until the async page read for pageIndex finishes, then inspects readStatus. If the device read ended with ReadStatus.Error, it throws FasterException reporting the failed page. It surfaces an underlying device/OS read failure from the checkpoint/log recovery path.","triggerScenarios":"Recovering or scanning a log/checkpoint whose device read of pageIndex failed — e.g. truncated or corrupted log file, disk I/O error, file removed or shrunk between checkpoint and recovery.","commonSituations":"Restoring from a checkpoint on a different machine with a missing/incomplete checkpoint directory, running out of disk/driver errors, or a log file corrupted by an earlier crash.","solutions":["Inspect the underlying exception/logs from the recovery device to identify the I/O failure (bad path, permissions, disk error).","Verify the checkpoint/log files exist and are complete; re-copy the full checkpoint set if it was partially transferred.","Fall back to an earlier known-good checkpoint if the latest one is corrupted."],"exampleFix":"// before\nvar device = Devices.CreateLogDevice(\"/mnt/log.dat\"); // path missing on new host\nvar store = new FasterKV<long, long>(1L << 20, logSettings);\nstore.Recover();\n// after\nif (!File.Exists(\"/mnt/log.dat\"))\n    throw new FileNotFoundException(\"Log device file missing before Recover\");\nvar device = Devices.CreateLogDevice(\"/mnt/log.dat\");\nvar store = new FasterKV<long, long>(1L << 20, logSettings);\nstore.Recover();","handlingStrategy":"try-catch","validationCode":"var logPath = \"/mnt/faster/log.dat\";\nif (!File.Exists(logPath) || new FileInfo(logPath).Length == 0)\n    throw new FileNotFoundException(\"Log device file missing or empty before Recover\", logPath);","typeGuard":null,"tryCatchPattern":"try { store.Recover(); }\ncatch (FasterException ex) when (ex.Message.Contains(\"Error reading page\"))\n{ logger.LogCritical(ex, \"Recovery device read failed; falling back to prior checkpoint\"); RestoreFromEarlierCheckpoint(); }","preventionTips":["Copy the entire checkpoint directory set atomically (log + checkpoint info) before recovering.","Verify file sizes/checksums after transferring checkpoints between machines.","Monitor disk health and retain at least two prior checkpoints."],"tags":["faster","io","recovery","device-read","csharp"],"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"}