{"record":{"id":"c9b4134e32d5d148","repo":"microsoft/FASTER","slug":"error-u","errorCode":null,"errorMessage":"Error: %u\n","messagePattern":"Error: %u\n","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"cc/src/core/persistent_memory_malloc.h","lineNumber":999,"sourceCode":"    Context(std::atomic<PageRecoveryStatus>& page_status_)\n      : page_status{ &page_status_ } {\n    }\n    /// The deep-copy constructor\n    Context(const Context& other)\n      : page_status{ other.page_status } {\n    }\n   protected:\n    Status DeepCopy_Internal(IAsyncContext*& context_copy) final {\n      return IAsyncContext::DeepCopy_Internal(*this, context_copy);\n    }\n   public:\n    std::atomic<PageRecoveryStatus>* page_status;\n  };\n\n  auto callback = [](IAsyncContext* ctxt, Status result, size_t bytes_transferred) {\n    CallbackContext<Context> context{ ctxt };\n    if(result != Status::Ok) {\n      log_error(\"Error: %u\\n\", static_cast<uint8_t>(result));\n    }\n    assert(context->page_status->load() == PageRecoveryStatus::IssuedRead);\n    context->page_status->store(PageRecoveryStatus::ReadDone);\n  };\n\n  for(uint32_t read_page = start_page; read_page < start_page + num_pages; ++read_page) {\n    if(!Page(read_page)) {\n      // Allocate a new page.\n      AllocatePage(read_page);\n    } else {\n      // Clear an old used page.\n      std::memset(Page(read_page), 0, kPageSize);\n    }\n    assert(recovery_status.page_status(read_page) == PageRecoveryStatus::NotStarted);\n    recovery_status.page_status(read_page).store(PageRecoveryStatus::IssuedRead);\n    PageStatus(read_page).LastFlushedUntilAddress.store(Address{ read_page + 1, 0 });\n    Context context{ recovery_status.page_status(read_page) };\n    RETURN_NOT_OK(read_file.ReadAsync(kPageSize * (read_page - file_start_page), Page(read_page),","sourceCodeStart":981,"sourceCodeEnd":1017,"githubUrl":"https://github.com/microsoft/FASTER/blob/321d872eabda6a0345c8bd76419f89723ed864ae/cc/src/core/persistent_memory_malloc.h#L981-L1017","documentation":"This log_error fires inside the page-recovery read callback of PersistentMemoryMalloc::Recover (async read of a previously flushed page back into memory). If the async read completes with a Status other than Status::Ok, the status is logged, but the callback then overwrites the page status to ReadDone anyway, so recovery may proceed with a page whose contents were never successfully read — leading to corrupted or missing log data after restart.","triggerScenarios":"Calling store->Recover() (or allocator Recover) after a restart/checkpoint, where the async read of a flushed page from the checkpoint/log file fails: missing or truncated log file, file offsets beyond EOF, device I/O error, or a checkpoint directory that does not match the requested checkpoint token.","commonSituations":"Recovering from a checkpoint directory that was copied incompletely or corrupted; disk failure or changed volume between checkpoint and recovery; pointing recovery at the wrong checkpoint token so required pages don't exist.","solutions":["Map the logged status code to the underlying read failure and verify the checkpoint/log files exist, are complete, and are readable","Recovery must be pointed at a valid, fully-flushed checkpoint token; list available checkpoints (e.g. via the checkpoint manager) and retry with the correct one","If files are corrupt, restore from an earlier healthy checkpoint or backup rather than trusting the partial recovery","Fix storage health/permissions issues and retry Recover before allowing the application to serve data"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before calling Recover, confirm the checkpoint files exist\nfor (const std::string& f : required_checkpoint_files) {\n  if (!std::filesystem::exists(checkpoint_dir / f) || std::filesystem::file_size(checkpoint_dir / f) == 0) {\n    // abort recovery: incomplete checkpoint, fall back to an earlier token\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  store->Recover(index_token, hybrid_log_token, dir_token);\n} catch (...) {\n  // NOTE: failed page reads are only logged ('Error: %u'), not thrown —\n  // scan logs for non-Ok statuses and treat any occurrence as failed recovery:\n  std::cerr << \"Recovery saw failed page reads; restore from an earlier checkpoint\\n\";\n}","preventionTips":["Never point Recover at a partially copied or hand-edited checkpoint directory","After any failed page-read log during recovery, re-verify or restore from a known-good checkpoint — ReadDone is set even on failure","Take and retain multiple checkpoint generations so a corrupt one can be abandoned","Ensure the checkpoint volume is stable (same device path, mounted, healthy) between checkpoint and recovery"],"tags":["recovery","async-io","file-read","checkpoint"],"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"}