apache/dolphinscheduler · error · RuntimeException

"The object being compared is not a TaskReadyForDispatchEven

Error message

"The object being compared is not a TaskReadyForDispatchEvent."

What it means

TaskDispatchableEvent implements Delayed and its compareTo assumes every other element in the delay queue is also a TaskDispatchableEvent. If compareTo is handed a different Delayed implementation (e.g. another kind of retry/scheduled event sharing the same DelayQueue), it throws RuntimeException with this legacy 'TaskReadyForDispatchEvent' message. It is an internal invariant check protecting the priority comparison logic.

Source

Thrown at dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/engine/task/dispatcher/event/TaskDispatchableEvent.java:48

    protected final V data;

    protected final int dispatchTimes;

    public TaskDispatchableEvent(long delayTimeMills, V data) {
        this(delayTimeMills, data, 0);
    }

    public TaskDispatchableEvent(long delayTimeMills, V data, int dispatchTimes) {
        super(delayTimeMills);
        this.data = checkNotNull(data, "data is null");
        this.dispatchTimes = dispatchTimes;
    }

    @Override
    public int compareTo(Delayed other) {
        if (!(other instanceof TaskDispatchableEvent)) {
            throw new RuntimeException("The object being compared is not a TaskReadyForDispatchEvent.");
        }

        @SuppressWarnings("unchecked")
        final TaskDispatchableEvent<V> otherEvent = (TaskDispatchableEvent<V>) other;

        // For two retry events, we should compare the priority first, since the task delay time has already been
        // expired.
        if (dispatchTimes > 0 && otherEvent.dispatchTimes > 0) {
            int priorityCompareResult = data.compareTo(otherEvent.data);
            if (priorityCompareResult != 0) {
                return priorityCompareResult;
            }
            return super.compareTo(otherEvent);
        }

        // For two new events, we should compare the delay time first, since the delay time is not expired.
        // For two evens, if one is new another is retry, we should compare the delay time first
        int delayTimeCompareResult = super.compareTo(otherEvent);

View on GitHub (pinned to 02eac45a1b)

Solutions

  1. Ensure only TaskDispatchableEvent instances are enqueued into the dispatcher's DelayQueue.
  2. Fix the legacy error message to match the current class name (TaskDispatchableEvent) for diagnosability.
  3. If multiple Delayed types must share a queue, replace the raw cast with instanceof-based comparison instead of throwing.
  4. Update any plugin/custom code that adds foreign Delayed events to the queue.

Example fix

// before
if (!(other instanceof TaskDispatchableEvent)) {
    throw new RuntimeException("The object being compared is not a TaskReadyForDispatchEvent.");
}

// after
if (!(other instanceof TaskDispatchableEvent)) {
    return 1; // or sort by getDelay() to interleave foreign Delayed types
}
final TaskDispatchableEvent<?> otherEvent = (TaskDispatchableEvent<?>) other;
Defensive patterns

Strategy: type-guard

Validate before calling

// before enqueueing into the dispatcher's DelayQueue
if (!(event instanceof TaskDispatchableEvent)) {
    throw new IllegalArgumentException("Only TaskDispatchableEvent may be enqueued");
}

Type guard

static <V> TaskDispatchableEvent<V> asDispatchable(Delayed d) {
    return d instanceof TaskDispatchableEvent<V>
        ? (TaskDispatchableEvent<V>) d
        : null;
}

Try / catch

try {
    queue.offer(event);
} catch (RuntimeException e) {
    if (e.getMessage().contains("not a TaskReadyForDispatchEvent")) {
        log.error("Foreign Delayed object in dispatch queue: {}", event.getClass(), e);
    } else { throw e; }
}

Prevention

When it happens

Trigger: Inserting or mixing a non-TaskDispatchableEvent Delayed object into the same DelayQueue used by the task dispatcher, causing priorityCompare -> compareTo to receive an incompatible element.

Common situations: Custom code or plugins enqueueing their own Delayed events into the dispatcher queue; refactors introducing a second Delayed event type into the shared queue; test harnesses substituting mock Delayed objects.

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.


AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06). Data as JSON: /api/errors/ab6781cc0cc59c44. Report an issue: GitHub.