apache/pulsar · error · WebApplicationException

${fullFunctionName} has not been assigned yet

Error message

${fullFunctionName} has not been assigned yet

What it means

After finding the assignment, restartFunctionInstance resolves the worker that owns it by scanning workerInfoList for the assignment's workerId. If no WorkerInfo matches (workerInfo stays null), the assigned worker is unknown — the manager throws WebApplicationException (BAD_REQUEST) with '<fullFunctionName> has not been assigned yet'.

Source

Thrown at pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/FunctionRuntimeManager.java:391

        }

        final String assignedWorkerId = assignment.getWorkerId();
        final String workerId = this.workerConfig.getWorkerId();

        if (assignedWorkerId.equals(workerId)) {
            stopFunction(FunctionCommon.getFullyQualifiedInstanceId(assignment.getInstance()), true);
            return;
        } else {
            // query other worker
            List<WorkerInfo> workerInfoList = this.membershipManager.getCurrentMembership();
            WorkerInfo workerInfo = null;
            for (WorkerInfo entry : workerInfoList) {
                if (assignment.getWorkerId().equals(entry.getWorkerId())) {
                    workerInfo = entry;
                }
            }
            if (workerInfo == null) {
                throw new WebApplicationException(Response.serverError().status(Status.BAD_REQUEST)
                        .type(MediaType.APPLICATION_JSON)
                        .entity(new ErrorData(fullFunctionName + " has not been assigned yet")).build());
            }

            if (uri == null) {
                throw new WebApplicationException(Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build());
            } else {
                URI redirect = UriBuilder.fromUri(uri).host(workerInfo.getWorkerHostname())
                        .port(workerInfo.getPort()).build();
                throw new WebApplicationException(Response.temporaryRedirect(redirect).build());
            }
        }
    }

    public synchronized void restartFunctionInstances(String tenant, String namespace, String functionName)
            throws Exception {
        final String fullFunctionName = String.format("%s/%s/%s", tenant, namespace, functionName);
        Collection<Assignment> assignments = this.findFunctionAssignments(tenant, namespace, functionName);

View on GitHub (pinned to 820761864e)

Solutions

  1. Wait for the scheduler to reschedule the orphaned instance (leadership scheduler runs periodically), then retry.
  2. Trigger/verify scheduler reconciliation — check leader logs for assignment updates and worker membership changes.
  3. If a worker was decommissioned, confirm it was properly deregistered so stale assignments are cleaned up.
  4. As a workaround, restart the entire function (restartFunctionInstances) to force fresh assignments.

Example fix

// before
admin.functions().restartFunctionInstance(tenant, ns, fn, 0); // may 400 if worker gone
// after
awaitAtMost(60, SECONDS).until(() -> {
    try {
        admin.functions().restartFunctionInstance(tenant, ns, fn, 0);
        return true;
    } catch (PulsarAdminException e) {
        return false; // rescheduling in progress, retry
    }
});
Defensive patterns

Strategy: retry

Validate before calling

FunctionStatus status = admin.functions().getFunctionStatus(tenant, ns, fn);
boolean assigned = status.getInstances().stream()
    .anyMatch(i -> i.getStatus().getWorkerId() != null);
if (!assigned) {
    // wait for scheduler to assign before restarting
}

Try / catch

try {
    admin.functions().restartFunctionInstance(tenant, ns, fn, instanceId);
} catch (PulsarAdminException e) {
    if (e.getStatusCode() == 400 && e.getMessage().contains("has not been assigned")) {
        Thread.sleep(retryDelayMs); // wait for rescheduling after worker loss
        admin.functions().restartFunctionInstance(tenant, ns, fn, instanceId);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: An assignment exists but its workerId is absent from the current membership list (workerInfoList) — typically because the worker that owned the instance died/left the cluster and membership hasn't been reconciled, or the assignment is stale mid-failover.

Common situations: Restart attempt during/just after a worker crash or cluster membership change; stale assignment records after failover; calling restart on the leader right after a worker was removed but before rescheduling finished.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/6e42e869534f3469. Report an issue: GitHub.