apache/druid · error · IllegalStateException
Can't find surrogate task[%s]
Error message
Can't find surrogate task[%s]
What it means
SurrogateAction delegates a TaskAction to a 'surrogate' task identified by surrogateId (e.g. when a supervisor-like task performs actions on behalf of another task). Before delegating, it looks the surrogate task up in task storage; if no task with that ID exists in storage, it throws this IllegalStateException. This is an internal consistency check: the caller referenced a task ID that the overlord has no record of.
Source
Thrown at indexing-service/src/main/java/org/apache/druid/indexing/common/actions/SurrogateAction.java:72
public ActionType getTaskAction()
{
return taskAction;
}
@Override
public TypeReference<ReturnType> getReturnTypeReference()
{
return taskAction.getReturnTypeReference();
}
@Override
public ReturnType perform(Task task, TaskActionToolbox toolbox)
{
final Optional<Task> maybeSurrogateTask = toolbox.getTaskStorage().getTask(surrogateId);
if (maybeSurrogateTask.isPresent()) {
return taskAction.perform(maybeSurrogateTask.get(), toolbox);
} else {
throw new ISE("Can't find surrogate task[%s]", surrogateId);
}
}
@Override
public String toString()
{
return "SurrogateAction{" +
"surrogateId='" + surrogateId + '\'' +
", taskAction=" + taskAction +
'}';
}
}
View on GitHub (pinned to 9b90983fd2)
Solutions
- Check that the surrogate task ID actually exists: query the overlord /druid/indexer/v1/tasks or task storage DB for the ID in the message.
- Re-run or resubmit the parent task so a fresh surrogate task is created before its actions are performed.
- If task cleanup is killing tasks too aggressively, increase task retention (keepAlive / kill task config) so dependent actions finish first.
- Verify custom code isn't fabricating or truncating surrogate task IDs; upgrade if this is a known Druid bug.
Example fix
// before
TaskActionClient client = toolbox.getTaskActionClient();
client.submit(new SurrogateAction<>(someStaleId, new LockListAction()));
// after
if (toolbox.getTaskStorage().getTask(surrogateId).isPresent()) {
client.submit(new SurrogateAction<>(surrogateId, new LockListAction()));
} else {
LOG.warn("surrogate task %s no longer exists, skipping", surrogateId);
} Defensive patterns
Strategy: validation
Validate before calling
Optional<Task> surrogate = toolbox.getTaskStorage().getTask(surrogateId);
if (!surrogate.isPresent()) {
throw new IllegalStateException("Surrogate task " + surrogateId + " does not exist; resubmit the parent task");
} Type guard
boolean surrogateExists(String id, TaskStorage storage) {
return storage.getTask(id).isPresent();
} Try / catch
try {
return actionClient.submit(new SurrogateAction<>(surrogateId, action));
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Can't find surrogate task")) {
// recreate/resubmit the parent task, then retry
} else throw e;
} Prevention
- Always create the surrogate task before submitting surrogate actions on its behalf.
- Don't kill or prune tasks while dependent delegating actions may still run.
- Log and verify surrogate task IDs when building custom delegation logic.
When it happens
Trigger: Submitting a surrogate TaskAction whose surrogateId refers to a task that was never created, has been killed/pruned from task storage, or whose ID was mistyped. Also occurs if the surrogate task completed and was removed before the delegating action ran.
Common situations: Overlord task storage cleaned up (e.g. kill tasks / short retention) while dependent tasks still reference old surrogate IDs; race between surrogate task completion and a queued action; bugs in custom task code forwarding wrong IDs after upgrades.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- can't start.
- can't stop.
- Cache reference is null
- pollingLookup id [%s] is closed
- Can't find lock for the interval of segment[%s]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/7df20a51f008f1ea.
Report an issue: GitHub.