{"record":{"id":"729d3a4b36a64ee1","repo":"apache/pulsar","slug":"worker-workerid-is-not-among-the-current-worker-729d3a","errorCode":null,"errorMessage":"Worker ${workerId} is not among the current workers in the system","messagePattern":"Worker (.+?) is not among the current workers in the system","errorType":"http","errorClass":"RestException","httpStatus":400,"severity":"error","filePath":"pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/WorkerImpl.java","lineNumber":282,"sourceCode":"\n        // Depending on which operations we decide to allow, we may add checks here to error/exception if\n        //      calledOnLeaderUri is true on a non-leader\n        //      calledOnLeaderUri is false on a leader\n        // For now, deal with everything.\n\n        if (worker().getLeaderService().isLeader()) {\n            try {\n                worker().getSchedulerManager().drainIfNotInProgress(workerId);\n            } catch (SchedulerManager.DrainInProgressException e) {\n                throw new RestException(Status.CONFLICT, \"Another drain is in progress\");\n            } catch (SchedulerManager.TooFewWorkersException e) {\n                throw new RestException(Status.BAD_REQUEST, \"Too few workers (need at least 2)\");\n            } catch (SchedulerManager.WorkerNotRemovedAfterPriorDrainException e) {\n                String errString = \"Worker \" + workerId + \" was not yet removed after a prior drain op; try later\";\n                throw new RestException(Status.PRECONDITION_FAILED, errString);\n            } catch (SchedulerManager.UnknownWorkerException e) {\n                String errString = \"Worker \" + workerId + \" is not among the current workers in the system\";\n                throw new RestException(Status.BAD_REQUEST, errString);\n            }\n        } else {\n            URI redirect = buildRedirectUriForDrainRelatedOp(uri, workerId);\n            log.info().attr(\"redirect\", redirect).log(\"Not leader; redirect URI=\");\n            throw new WebApplicationException(Response.temporaryRedirect(redirect).build());\n        }\n    }\n\n    @Override\n    public LongRunningProcessStatus getDrainStatus(final URI uri, final String inWorkerId,\n                                                   final AuthenticationParameters authParams,\n                                                   boolean calledOnLeaderUri) {\n        if (!isWorkerServiceAvailable()) {\n            throwUnavailableException();\n        }\n\n        final String actualWorkerId = worker().getWorkerConfig().getWorkerId();\n        final String workerId = (inWorkerId == null || inWorkerId.isEmpty()) ? actualWorkerId : inWorkerId;","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/WorkerImpl.java#L264-L300","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before: assume hostname is the workerId\nadmin.functions().drain(hostname);\n// after: resolve actual registered worker IDs first\nList<WorkerInfo> workers = admin.functions().getCluster();\nif (workers.stream().anyMatch(w -> w.getWorkerId().equals(workerId))) {\n    admin.functions().drain(workerId);\n}","handlingStrategy":"validation","validationCode":"List<WorkerInfo> workers = admin.functions().getCluster();\nif (workers.stream().noneMatch(w -> w.getWorkerId().equals(workerId))) {\n    throw new IllegalArgumentException(\"workerId not registered: \" + workerId);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["rest-api","drain","invalid-parameter"],"backgroundTag":"unknown-worker-id","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}