flowable/flowable-engine · error · ActivitiIllegalArgumentException

The number of job retries must be a non-negative Integer…

Error message

The number of job retries must be a non-negative Integer, but '" + retries + "' has been provided.

What it means

Constructor validation in flowable5 SetJobRetriesCmd: the retries value is negative; the engine requires a non-negative retry count, and the supplied value is echoed in the message.

Solutions

  1. Clamp the retry count before calling: Math.max(0, retries).
  2. Validate user/config input to ensure retries >= 0.
  3. Fix the computation that produces the negative value.

Example fix

// before
managementService.setJobRetries(jobId, retries); // retries may be negative
// after
managementService.setJobRetries(jobId, Math.max(0, retries));
Defensive patterns

Strategy: validation

Validate before calling

if (retries < 0) throw new IllegalArgumentException("retries must be >= 0");

Try / catch

try { managementService.setJobRetries(jobId, retries); }
catch (ActivitiIllegalArgumentException e) { log.error("invalid retries value {}", retries); }

Prevention

When it happens

Trigger: new SetJobRetriesCmd(jobId, -1) or ManagementService.setJobRetries(jobId, negativeNumber).

Common situations: Retry count computed by subtracting attempts (going below zero), user input not validated, or off-by-one logic when decrementing retries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/ef370b2a7a98c769. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/SetJobRetriesCmd.java:43

import org.flowable.common.engine.impl.interceptor.EngineConfigurationConstants;
import org.flowable.job.api.Job;

/**
 * @author Falko Menge
 */
public class SetJobRetriesCmd implements Command<Void>, Serializable {

    private static final long serialVersionUID = 1L;

    private final String jobId;
    private final int retries;

    public SetJobRetriesCmd(String jobId, int retries) {
        if (jobId == null || jobId.length() < 1) {
            throw new ActivitiIllegalArgumentException("The job id is mandatory, but '" + jobId + "' has been provided.");
        }
        if (retries < 0) {
            throw new ActivitiIllegalArgumentException("The number of job retries must be a non-negative Integer, but '" + retries + "' has been provided.");
        }
        this.jobId = jobId;
        this.retries = retries;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        JobEntity job = commandContext
                .getJobEntityManager()
                .findJobById(jobId);
        if (job != null) {
            job.setRetries(retries);

            if (commandContext.getEventDispatcher().isEnabled()) {
                commandContext.getEventDispatcher().dispatchEvent(
                        ActivitiEventBuilder.createEntityEvent(FlowableEngineEventType.ENTITY_UPDATED, job),
                        EngineConfigurationConstants.KEY_PROCESS_ENGINE_CONFIG);
            }

View on GitHub (pinned to d6d39ce1c6)