microsoft/FASTER · error

Failed to schedule work:

Error message

Failed to schedule work: 

What it means

On Windows, WindowsPtpThreadPool::Schedule wraps a task with CreateThreadpoolWork to submit it to the thread pool. If that Win32 call fails, the error is formatted (with GetLastError) and printed as 'Failed to schedule work: ...' and Status::Aborted is returned to the caller.

Solutions

  1. Read the appended FormatWin32AndHRESULT text on stderr to identify the underlying Win32 error
  2. Check system resource availability (handles, memory, thread pool limits)
  3. Retry the operation; if persistent, restart the process and re-initialize FASTER
  4. Verify the process is a supported Windows build and the thread pool environment was created correctly

Example fix

// before
auto s = kv.ScheduleBackgroundWork(...); // assumes Ok
// after
Status s = kv.Checkpoint(...);
if (s != Status::Ok) { /* handle scheduling failure, retry */ }
Defensive patterns

Strategy: retry

Validate before calling

null

Try / catch

Status s = op();
if (s == Status::Aborted) {
  // inspect stderr 'Failed to schedule work: <win32 error>'
  // wait briefly and retry, or fail the request
}

Prevention

When it happens

Trigger: Calling faster K/V operations that schedule background work (checkpoint, recovery, I/O callbacks) when CreateThreadpoolWork returns NULL — typically due to Win32 resource exhaustion or an invalid callback environment.

Common situations: Systems under heavy thread/handle exhaustion, running on constrained Windows environments, misconfigured callback environments after initialization issues.

Related errors


AI-assisted analysis of microsoft/FASTER@321d872eab (2026-09-15). Data as JSON: /api/errors/f3e9c09a839b6eb6. Report an issue: GitHub.

Appendix: source

Thrown at cc/src/environment/file_windows.cc:184

  ::CloseThreadpool(pool_);

  delete callback_environment_;
}

Status WindowsPtpThreadPool::Schedule(Task task, void* task_parameters) {
  auto info = alloc_context<TaskInfo>(sizeof(TaskInfo));
  if(!info.get()) return Status::OutOfMemory;
  new(info.get()) TaskInfo();

  info->task = task;
  info->task_parameters = task_parameters;

  PTP_WORK_CALLBACK ptp_callback = TaskStartSpringboard;
  PTP_WORK work = CreateThreadpoolWork(ptp_callback, info.get(), callback_environment_);
  if(!work) {
    std::stringstream ss;
    ss << "Failed to schedule work: " << FormatWin32AndHRESULT(::GetLastError());
    fprintf(stderr, "%s\n", ss.str().c_str());
    return Status::Aborted;
  }
  SubmitThreadpoolWork(work);
  info.release();

  return Status::Ok;
}

void CALLBACK WindowsPtpThreadPool::TaskStartSpringboard(PTP_CALLBACK_INSTANCE instance,
    PVOID parameter, PTP_WORK work) {
  auto info = make_context_unique_ptr<TaskInfo>(reinterpret_cast<TaskInfo*>(parameter));
  info->task(info->task_parameters);
  CloseThreadpoolWork(work);
}

Status ThreadPoolFile::Open(FileCreateDisposition create_disposition, const FileOptions& options,
                            ThreadPoolIoHandler* handler, bool* exists) {
  DWORD flags = FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_OVERLAPPED;

View on GitHub (pinned to 321d872eab)