apache/seatunnel · error · NoEnoughResourceException

can't apply resource request

Error message

can't apply resource request: ${r}

What it means

During slot pre-check, requestSlots iterates the requested ResourceProfiles and picks a worker whose remaining capacity can satisfy each profile. When no worker can provide the requested resource, it adds a failed future that throws NoEnoughResourceException so the whole request fails fast without retry churn.

Solutions

  1. Reduce the job's per-pipeline resource declaration to fit worker capacity
  2. Add/verify node tags so workers match the requested tags
  3. Scale the cluster: add worker nodes or increase slot counts per worker
  4. Check worker available resources via REST to confirm the shortfall

Example fix

// before: tags = ["gpu"] with no gpu worker
source { ... }
// after: remove tag or tag a worker with gpu
source { ... } // and ensure worker node has matching tag
Defensive patterns

Strategy: validation

Validate before calling

// pre-check worker capacity
GET /hazelcast/rest/maps/worker-profile  # confirm cpu/mem/tags satisfy ResourceProfile

Try / catch

try {
    future.get();
} catch (ExecutionException e) {
    if (e.getCause() instanceof NoEnoughResourceException) {
        log.warn("No worker satisfies profile: " + profile);
    }
}

Prevention

When it happens

Trigger: ResourceRequestHandler.requestSlots called with a ResourceProfile larger than any worker's unallocated CPU/memory, or with tags that no live worker matches.

Common situations: Job declares higher cpu/memory than the biggest worker; all workers busy; tag-based scheduling with tags not configured on any node; workers newly joined but not yet registered.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/135377d328076c7f. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/resourcemanager/ResourceRequestHandler.java:202

    private List<CompletableFuture<SlotAndWorkerProfile>> requestSlots(
            List<ResourceProfile> requestProfile) {
        List<CompletableFuture<SlotAndWorkerProfile>> allRequestFuture = new ArrayList<>();

        for (int i = 0; i < requestProfile.size(); i++) {
            ResourceProfile r = requestProfile.get(i);
            Optional<WorkerProfile> workerProfile = preCheckWorkerResource(r);
            if (workerProfile.isPresent()) {
                // request slot to member
                CompletableFuture<SlotAndWorkerProfile> internalCompletableFuture =
                        singleResourceRequestToMember(i, r, workerProfile.get());
                allRequestFuture.add(internalCompletableFuture);
            } else {
                // if no worker can provide the resource, we should return a failed future
                LOGGER.fine("pre check worker resource failed, can't apply resource request: " + r);
                allRequestFuture.add(
                        CompletableFuture.supplyAsync(
                                () -> {
                                    throw new NoEnoughResourceException(
                                            "can't apply resource request: " + r);
                                }));
            }
        }
        return allRequestFuture;
    }

    private void completeRequestWithException(Throwable e) {
        if (completableFuture.completeExceptionally(e)) {
            releaseAllResourceInternal();
        }
    }

    private void addSlotToCacheMap(int index, SlotProfile slotProfile) {
        // null value means the slot request failed, no suitable slot found
        if (null != slotProfile) {
            resultSlotProfiles.put(index, slotProfile);
            if (resultSlotProfiles.size() == resourceProfile.size()) {

View on GitHub (pinned to cf67b549a7)