microsoft/FASTER · error · FasterException
Error reading page from device
Error message
Error reading page {pageIndex} from device What it means
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.
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.
Example fix
// before
var device = Devices.CreateLogDevice("/mnt/log.dat"); // path missing on new host
var store = new FasterKV<long, long>(1L << 20, logSettings);
store.Recover();
// after
if (!File.Exists("/mnt/log.dat"))
throw new FileNotFoundException("Log device file missing before Recover");
var device = Devices.CreateLogDevice("/mnt/log.dat");
var store = new FasterKV<long, long>(1L << 20, logSettings);
store.Recover(); Defensive patterns
Strategy: try-catch
Validate before calling
var logPath = "/mnt/faster/log.dat";
if (!File.Exists(logPath) || new FileInfo(logPath).Length == 0)
throw new FileNotFoundException("Log device file missing or empty before Recover", logPath); Try / catch
try { store.Recover(); }
catch (FasterException ex) when (ex.Message.Contains("Error reading page"))
{ logger.LogCritical(ex, "Recovery device read failed; falling back to prior checkpoint"); RestoreFromEarlierCheckpoint(); } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Unexpected entry type
- Unable to set first valid segment to
- Unable to set last valid segment to
- Session named already exists in recovery info, use…
- Unable to find session named
AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15).
Data as JSON: /api/errors/9352a48ac8046b17.
Report an issue: GitHub.
Appendix: source
Thrown at cs/src/core/Index/Recovery/Recovery.cs:72
internal void SignalRead(int pageIndex)
{
this.readStatus[pageIndex] = ReadStatus.Done;
this.readSemaphore.Release();
}
internal void SignalReadError(int pageIndex)
{
this.readStatus[pageIndex] = ReadStatus.Error;
this.readSemaphore.Release();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void WaitRead(int pageIndex)
{
while (this.readStatus[pageIndex] == ReadStatus.Pending)
this.readSemaphore.Wait();
if (this.readStatus[pageIndex] == ReadStatus.Error)
throw new FasterException($"Error reading page {pageIndex} from device");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal async ValueTask WaitReadAsync(int pageIndex, CancellationToken cancellationToken)
{
while (this.readStatus[pageIndex] == ReadStatus.Pending)
await this.readSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
if (this.readStatus[pageIndex] == ReadStatus.Error)
throw new FasterException($"Error reading page {pageIndex} from device");
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void SignalFlushed(int pageIndex)
{
this.flushStatus[pageIndex] = FlushStatus.Done;
this.flushSemaphore.Release();
}
View on GitHub (pinned to 321d872eab)