kestra-io/kestra · error · IllegalArgumentException
Only QUEUED execution can be unqueued
Error message
Only QUEUED execution can be unqueued
What it means
The `ConcurrencyLimitService.unqueue()` method transitions a queued execution to a target state. The execution must currently be in the `QUEUED` state — if it is in any other state (RUNNING, SUCCESS, FAILED, etc.), an `IllegalArgumentException` is thrown. Only QUEUED executions are tracked in the `ExecutionQueuedStateStore` and can be removed/unqueued.
Source
Thrown at core/src/main/java/io/kestra/core/services/ConcurrencyLimitService.java:28
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
@Singleton
public class ConcurrencyLimitService {
private static final Set<State.Type> VALID_TARGET_STATES = EnumSet.of(State.Type.RUNNING, State.Type.CANCELLED, State.Type.FAILED);
@Inject
private ExecutionQueuedStateStore executionQueuedStateStore;
/**
* Unqueue a queued execution.
*
* @throws IllegalArgumentException in case the execution is not queued or is transitioned to an unsupported state.
*/
public Execution unqueue(Execution execution, State.Type state) {
if (execution.getState().getCurrent() != State.Type.QUEUED) {
throw new IllegalArgumentException("Only QUEUED execution can be unqueued");
}
state = (state == null) ? State.Type.RUNNING : state;
// Validate the target state, throwing an exception if the state is invalid
if (!VALID_TARGET_STATES.contains(state)) {
throw new IllegalArgumentException("Invalid target state: " + state + ". Valid states are: " + VALID_TARGET_STATES);
}
executionQueuedStateStore.remove(execution);
return execution.withState(state);
}
}
View on GitHub (pinned to 823fada927)
Solutions
- Check `execution.getState().getCurrent() == State.Type.QUEUED` before calling `unqueue()`.
- Handle the case gracefully — if the execution is already past QUEUED, it may have been processed by another caller.
- Use optimistic locking or idempotency checks to handle race conditions.
Example fix
// before
executionService.unqueue(execution, State.Type.RUNNING);
// after
if (execution.getState().getCurrent() == State.Type.QUEUED) {
execution = executionService.unqueue(execution, State.Type.RUNNING);
} Defensive patterns
Strategy: type-guard
Validate before calling
// Check execution state before unqueueing
import io.kestra.core.models.flows.State;
public static boolean isUnqueueable(Execution execution) {
return execution.getState().getCurrent() == State.Type.QUEUED;
}
if (isUnqueueable(execution)) {
execution = concurrencyLimitService.unqueue(execution, targetState);
} Type guard
import { State } from './types';
function isQueued(state: State.Type): boolean {
return state === 'QUEUED';
} Try / catch
try {
execution = concurrencyLimitService.unqueue(execution, state);
} catch (IllegalArgumentException e) {
if (e.getMessage().equals("Only QUEUED execution can be unqueued")) {
// already unqueued by another caller, or state changed
log.info("Execution {} is no longer queued, skipping unqueue", execution.getId());
} else {
throw e;
}
} Prevention
- Always check `execution.getState().getCurrent() == State.Type.QUEUED` before unqueueing.
- Handle the case where the execution was already unqueued by another caller (race condition).
- Log the current state when the guard fails to aid debugging.
When it happens
Trigger: Calling `unqueue()` on an execution that has already been unqueued (moved to RUNNING). Calling it on an execution that was never queued (e.g., it went straight to RUNNING because no concurrency limit applied). A race condition where the execution was unqueued by another thread before this call.
Common situations: A concurrency limit was reached, an execution was queued, then manually or automatically unqueued; a second unqueue attempt fails. The execution state changed between a status check and the unqueue call.
Related errors
- Invalid target state: {state}. Valid states are: {VALID_TARG
- Execution '{executionId}' is not paused, can't resume it
- Execution must be terminated or paused and not killed to be
- Both `namespace` and `flowId` must be set when `executionId`
- `namespace` and `flowId` should only be set when `executionI
AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14).
Data as JSON: /api/errors/3182c9e752bee4aa.
Report an issue: GitHub.