apache/pulsar · error · RestException
Worker ${workerId} is not among the current workers in the s
Error message
Worker ${workerId} is not among the current workers in the system What it means
This HTTP 400 error is returned by the drain endpoint when the requested workerId is not among the currently registered workers. SchedulerManager throws UnknownWorkerException because it cannot drain a worker it does not know about.
Source
Thrown at pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/WorkerImpl.java:282
// Depending on which operations we decide to allow, we may add checks here to error/exception if
// calledOnLeaderUri is true on a non-leader
// calledOnLeaderUri is false on a leader
// For now, deal with everything.
if (worker().getLeaderService().isLeader()) {
try {
worker().getSchedulerManager().drainIfNotInProgress(workerId);
} catch (SchedulerManager.DrainInProgressException e) {
throw new RestException(Status.CONFLICT, "Another drain is in progress");
} catch (SchedulerManager.TooFewWorkersException e) {
throw new RestException(Status.BAD_REQUEST, "Too few workers (need at least 2)");
} catch (SchedulerManager.WorkerNotRemovedAfterPriorDrainException e) {
String errString = "Worker " + workerId + " was not yet removed after a prior drain op; try later";
throw new RestException(Status.PRECONDITION_FAILED, errString);
} catch (SchedulerManager.UnknownWorkerException e) {
String errString = "Worker " + workerId + " is not among the current workers in the system";
throw new RestException(Status.BAD_REQUEST, errString);
}
} else {
URI redirect = buildRedirectUriForDrainRelatedOp(uri, workerId);
log.info().attr("redirect", redirect).log("Not leader; redirect URI=");
throw new WebApplicationException(Response.temporaryRedirect(redirect).build());
}
}
@Override
public LongRunningProcessStatus getDrainStatus(final URI uri, final String inWorkerId,
final AuthenticationParameters authParams,
boolean calledOnLeaderUri) {
if (!isWorkerServiceAvailable()) {
throwUnavailableException();
}
final String actualWorkerId = worker().getWorkerConfig().getWorkerId();
final String workerId = (inWorkerId == null || inWorkerId.isEmpty()) ? actualWorkerId : inWorkerId;View on GitHub (pinned to 820761864e)
Solutions
- List current workers via GET /admin/v2/worker/cluster and use an exact registered workerId
- Correct the workerId in the request (it must match the worker's registered ID, not necessarily the hostname)
- Skip the drain if the worker already left — its instances are already reassigned
Example fix
// before: assume hostname is the workerId
admin.functions().drain(hostname);
// after: resolve actual registered worker IDs first
List<WorkerInfo> workers = admin.functions().getCluster();
if (workers.stream().anyMatch(w -> w.getWorkerId().equals(workerId))) {
admin.functions().drain(workerId);
} Defensive patterns
Strategy: validation
Validate before calling
List<WorkerInfo> workers = admin.functions().getCluster();
if (workers.stream().noneMatch(w -> w.getWorkerId().equals(workerId))) {
throw new IllegalArgumentException("workerId not registered: " + workerId);
} Prevention
- Resolve workerIds from GET /admin/v2/worker/cluster instead of hostnames
- Skip drain for workers already deregistered
- Keep an up-to-date mapping of running workers to their registered IDs
When it happens
Trigger: Calling PUT /admin/v2/worker/drain/{workerId} with a workerId that is not in the membership manager's current worker list (typo, worker already stopped, or stale cached ID).
Common situations: Draining a worker that already crashed or was deregistered; copy-pasting a hostname/workerId that doesn't match the registered workerId; retrying drain after the worker already left.
Related errors
- Another drain is in progress
- Worker ${workerId} was not yet removed after a prior drain o
- cluster data is required
- Cluster already exists
- Peer cluster ${peerCluster} does not exist
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/729d3a4b36a64ee1.
Report an issue: GitHub.