flowable/flowable-engine · error · FlowableIllegalArgumentException
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
The SetJobRetriesCmd constructor also validates the retries parameter and throws FlowableIllegalArgumentException when retries is negative. Retry counts must be >= 0 because they configure how many more times a failed job may be attempted; a negative value is nonsensical.
Solutions
- Clamp the retry count to Math.max(0, retries) before calling setJobRetries.
- Validate configuration values for retries are non-negative at startup.
- Fix the arithmetic that can produce a negative count.
Example fix
// before managementService.setJobRetries(jobId, currentRetries - decrements); // after int newRetries = Math.max(0, currentRetries - decrements); managementService.setJobRetries(jobId, newRetries);
Defensive patterns
Strategy: validation
Validate before calling
if (retries < 0) throw new IllegalArgumentException("retries must be >= 0"); Type guard
boolean validRetries = retries >= 0;
Try / catch
try { managementService.setJobRetries(jobId, retries); } catch (FlowableIllegalArgumentException e) { log.error("Invalid retries value: {}", e.getMessage()); } Prevention
- Clamp computed retry counts with Math.max(0, n)
- Validate retry-related config values at startup
- Use unsigned semantics/DTO validation (>=0) in your API layer
When it happens
Trigger: Calling ManagementService.setJobRetries(jobId, retries) with retries < 0, e.g. computing retries via subtraction that underflows or a config value parsed incorrectly.
Common situations: Decrementing current retries without flooring at zero; property files/env vars with negative or misparsed values; arithmetic on retry counts in retry-management tooling.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- batchSize has to be larger than 0
- No job found with id
- The job id is mandatory, but
- A channel key detection value is required for inbound…
- A channel key detection value is required for the channel…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/8e59122678ba9295.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/SetJobRetriesCmd.java:46
/**
* @author Falko Menge
*/
public class SetJobRetriesCmd implements Command<Void>, Serializable {
private static final long serialVersionUID = 1L;
protected JobServiceConfiguration jobServiceConfiguration;
protected final String jobId;
protected final int retries;
public SetJobRetriesCmd(String jobId, int retries, JobServiceConfiguration jobServiceConfiguration) {
if (jobId == null || jobId.length() < 1) {
throw new FlowableIllegalArgumentException("The job id is mandatory, but '" + jobId + "' has been provided.");
}
if (retries < 0) {
throw new FlowableIllegalArgumentException("The number of job retries must be a non-negative Integer, but '" + retries + "' has been provided.");
}
this.jobId = jobId;
this.retries = retries;
this.jobServiceConfiguration = jobServiceConfiguration;
}
@Override
public Void execute(CommandContext commandContext) {
JobEntity job = jobServiceConfiguration.getJobEntityManager().findById(jobId);
if (job != null) {
job.setRetries(retries);
FlowableEventDispatcher eventDispatcher = jobServiceConfiguration.getEventDispatcher();
if (eventDispatcher != null && eventDispatcher.isEnabled()) {
eventDispatcher.dispatchEvent(FlowableJobEventBuilder.createEntityEvent(FlowableEngineEventType.ENTITY_UPDATED, job),
jobServiceConfiguration.getEngineName());
}View on GitHub (pinned to d6d39ce1c6)