apache/druid · error · IllegalStateException

Lock dataSource[%s] != task dataSource[%s]

Error message

Lock dataSource[%s] != task dataSource[%s]

What it means

AbstractFixedIntervalTask.getAndCheckLock fetches the single task lock for the task and verifies it matches the task's own datasource (and interval). If the lock's datasource differs from the task's datasource, internal lock/bookkeeping state is inconsistent, so it throws this ISE. It confirms the task only operates under locks that actually belong to it.

Source

Thrown at indexing-service/src/main/java/org/apache/druid/indexing/common/task/AbstractFixedIntervalTask.java:111

  @JsonProperty
  public Interval getInterval()
  {
    return interval;
  }

  @Override
  public void stopGracefully(TaskConfig taskConfig)
  {
  }

  TaskLock getAndCheckLock(TaskToolbox toolbox) throws IOException
  {
    // Confirm we have a lock (will throw if there isn't exactly one element)
    final TaskLock myLock = Iterables.getOnlyElement(getTaskLocks(toolbox.getTaskActionClient()));

    if (!myLock.getDataSource().equals(getDataSource())) {
      throw new ISE("Lock dataSource[%s] != task dataSource[%s]", myLock.getDataSource(), getDataSource());
    }

    if (!myLock.getInterval().equals(getInterval())) {
      throw new ISE("Lock interval[%s] != task interval[%s]", myLock.getInterval(), getInterval());
    }
    return myLock;
  }
}

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Check the task spec's dataSource matches what the task was actually submitted with; resubmit with a consistent spec.
  2. If a custom subclass overrides getTaskLocks, ensure it filters locks by the task's own ID/datasource.
  3. Inspect task lock records in the metadata store for corruption; clean stale locks and restart the task.
  4. Upgrade Druid if this occurs after an overlord failover with no custom code (known state-consistency bugs).

Example fix

// before
@Override
protected List<TaskLock> getTaskLocks(TaskActionClient client) {
  return client.submit(new LockListAction()); // returns locks for ALL tasks
}
// after
@Override
protected List<TaskLock> getTaskLocks(TaskActionClient client) {
  return client.submit(new TaskLocksAcquireAction...) // or filter LockListAction result to this task's id/datasource
}
Defensive patterns

Strategy: validation

Validate before calling

List<TaskLock> locks = client.submit(new LockListAction());
for (TaskLock lock : locks) {
  if (!lock.getDataSource().equals(taskDataSource)) {
    throw new IllegalStateException("Lock datasource mismatch: " + lock.getDataSource());
  }
}

Type guard

boolean lockBelongsToTask(TaskLock lock, String taskDataSource) {
  return lock != null && taskDataSource.equals(lock.getDataSource());
}

Try / catch

try {
  TaskLock lock = fixedTask.getAndCheckLock(toolbox);
} catch (IllegalStateException e) {
  if (e.getMessage().contains("Lock dataSource")) {
    // inspect lock storage for corruption/stale locks; restart the task after cleanup
  } else throw e;
}

Prevention

When it happens

Trigger: getTaskLocks returns a lock whose dataSource differs from the task's datasource — e.g. getTaskLocks overridden/returning foreign locks, lock storage corruption, or a custom task subclass mixing up datasource configuration.

Common situations: Custom task subclasses overriding getTaskLocks incorrectly; datasource renamed mid-task; metadata-store/overlord state corruption after failover; copy-pasted task code with mismatched datasource fields.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/c17cc1878bbd0a30. Report an issue: GitHub.