{"record":{"id":"ef370b2a7a98c769","repo":"flowable/flowable-engine","slug":"the-number-of-job-retries-must-be-a-non-negative-i-ef370b","errorCode":null,"errorMessage":"The number of job retries must be a non-negative Integer, but '\" + retries + \"' has been provided.","messagePattern":"The number of job retries must be a non-negative Integer, but '\" \\+ retries \\+ \"' has been provided\\.","errorType":"exception","errorClass":"ActivitiIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/SetJobRetriesCmd.java","lineNumber":43,"sourceCode":"import org.flowable.common.engine.impl.interceptor.EngineConfigurationConstants;\nimport org.flowable.job.api.Job;\n\n/**\n * @author Falko Menge\n */\npublic class SetJobRetriesCmd implements Command<Void>, Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    private final String jobId;\n    private final int retries;\n\n    public SetJobRetriesCmd(String jobId, int retries) {\n        if (jobId == null || jobId.length() < 1) {\n            throw new ActivitiIllegalArgumentException(\"The job id is mandatory, but '\" + jobId + \"' has been provided.\");\n        }\n        if (retries < 0) {\n            throw new ActivitiIllegalArgumentException(\"The number of job retries must be a non-negative Integer, but '\" + retries + \"' has been provided.\");\n        }\n        this.jobId = jobId;\n        this.retries = retries;\n    }\n\n    @Override\n    public Void execute(CommandContext commandContext) {\n        JobEntity job = commandContext\n                .getJobEntityManager()\n                .findJobById(jobId);\n        if (job != null) {\n            job.setRetries(retries);\n\n            if (commandContext.getEventDispatcher().isEnabled()) {\n                commandContext.getEventDispatcher().dispatchEvent(\n                        ActivitiEventBuilder.createEntityEvent(FlowableEngineEventType.ENTITY_UPDATED, job),\n                        EngineConfigurationConstants.KEY_PROCESS_ENGINE_CONFIG);\n            }","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/SetJobRetriesCmd.java#L25-L61","documentation":"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.","triggerScenarios":"new SetJobRetriesCmd(jobId, -1) or ManagementService.setJobRetries(jobId, negativeNumber).","commonSituations":"Retry count computed by subtracting attempts (going below zero), user input not validated, or off-by-one logic when decrementing retries.","solutions":["Clamp the retry count before calling: Math.max(0, retries).","Validate user/config input to ensure retries >= 0.","Fix the computation that produces the negative value."],"exampleFix":"// before\nmanagementService.setJobRetries(jobId, retries); // retries may be negative\n// after\nmanagementService.setJobRetries(jobId, Math.max(0, retries));","handlingStrategy":"validation","validationCode":"if (retries < 0) throw new IllegalArgumentException(\"retries must be >= 0\");","typeGuard":null,"tryCatchPattern":"try { managementService.setJobRetries(jobId, retries); }\ncatch (ActivitiIllegalArgumentException e) { log.error(\"invalid retries value {}\", retries); }","preventionTips":["Clamp counters with Math.max(0, retries)","Validate user input at the boundary","Use range-checked setters for retry configuration"],"tags":["job","illegal-argument","validation","negative-value"],"backgroundTag":"argument-out-of-range","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}