databendlabs/databend · error

ExecutorTask::None => unreachable!()

Error message

ExecutorTask::None => unreachable!()

What it means

Panic raised by `QueryExecutorTasks::push_task` when it receives `ExecutorTask::None`. The executor treats `None` as a sentinel that must never enter a worker's task queue; receiving it means the new query executor's task production logic violated its own invariant.

Solutions

  1. Trace the producer of the task to find where `ExecutorTask::None` escaped the scheduler
  2. Replace the sentinel with an explicit error at the call site rather than `unreachable!()`
  3. Run the failing query with executor tracing enabled to identify the scheduling step
  4. Check for refactoring regressions in query_executor_tasks.rs

Example fix

// before
ExecutorTask::None => unreachable!(),
// after
ExecutorTask::None => return Err(ErrorCode::Internal("ExecutorTask::None pushed to worker queue")),
Defensive patterns

Strategy: type-guard

Validate before calling

if matches!(task, ExecutorTask::None) { return Err(ErrorCode::Internal("task is ExecutorTask::None")); }

Type guard

fn is_schedulable(t: &ExecutorTask) -> bool { !matches!(t, ExecutorTask::None) }

Prevention

When it happens

Trigger: Calling `push_task` on the new query executor's task set with an `ExecutorTask::None` value instead of a Sync/Async/AsyncCompleted task.

Common situations: Bug in the new executor's scheduling code, or third-party code/tests constructing tasks manually and pushing a default-initialized `None` task.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11). Data as JSON: /api/errors/9774334bb453115b. Report an issue: GitHub.

Appendix: source

Thrown at src/query/service/src/pipelines/executor/query_executor_tasks.rs:292

            }
        }

        ExecutorTask::None
    }

    pub fn push_task(&mut self, worker_id: usize, task: ExecutorTask) {
        self.tasks_size += 1;
        debug_assert!(
            worker_id < self.workers_sync_tasks.len(),
            "out of index, {}, {}",
            worker_id,
            self.workers_sync_tasks.len()
        );
        let sync_queue = &mut self.workers_sync_tasks[worker_id];
        let completed_queue = &mut self.workers_completed_async_tasks[worker_id];

        match task {
            ExecutorTask::None => unreachable!(),
            ExecutorTask::Sync(processor) => sync_queue.push_back(processor),
            ExecutorTask::Async(_) => unreachable!("used for new executor"),
            ExecutorTask::AsyncCompleted(task) => completed_queue.push_back(task),
        }
    }
}

View on GitHub (pinned to 288d84d76e)