{"record":{"id":"8e59122678ba9295","repo":"flowable/flowable-engine","slug":"the-number-of-job-retries-must-be-a-non-negative-i","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 '(.+?)' has been provided\\.","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/SetJobRetriesCmd.java","lineNumber":46,"sourceCode":"\n/**\n * @author Falko Menge\n */\npublic class SetJobRetriesCmd implements Command<Void>, Serializable {\n\n    private static final long serialVersionUID = 1L;\n    \n    protected JobServiceConfiguration jobServiceConfiguration;\n\n    protected final String jobId;\n    protected final int retries;\n\n    public SetJobRetriesCmd(String jobId, int retries, JobServiceConfiguration jobServiceConfiguration) {\n        if (jobId == null || jobId.length() < 1) {\n            throw new FlowableIllegalArgumentException(\"The job id is mandatory, but '\" + jobId + \"' has been provided.\");\n        }\n        if (retries < 0) {\n            throw new FlowableIllegalArgumentException(\"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        this.jobServiceConfiguration = jobServiceConfiguration;\n    }\n\n    @Override\n    public Void execute(CommandContext commandContext) {\n        JobEntity job = jobServiceConfiguration.getJobEntityManager().findById(jobId);\n        if (job != null) {\n\n            job.setRetries(retries);\n\n            FlowableEventDispatcher eventDispatcher = jobServiceConfiguration.getEventDispatcher();\n            if (eventDispatcher != null && eventDispatcher.isEnabled()) {\n                eventDispatcher.dispatchEvent(FlowableJobEventBuilder.createEntityEvent(FlowableEngineEventType.ENTITY_UPDATED, job),\n                        jobServiceConfiguration.getEngineName());\n            }","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/SetJobRetriesCmd.java#L28-L64","documentation":"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.","triggerScenarios":"Calling ManagementService.setJobRetries(jobId, retries) with retries < 0, e.g. computing retries via subtraction that underflows or a config value parsed incorrectly.","commonSituations":"Decrementing current retries without flooring at zero; property files/env vars with negative or misparsed values; arithmetic on retry counts in retry-management tooling.","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."],"exampleFix":"// before\nmanagementService.setJobRetries(jobId, currentRetries - decrements);\n// after\nint newRetries = Math.max(0, currentRetries - decrements);\nmanagementService.setJobRetries(jobId, newRetries);","handlingStrategy":"validation","validationCode":"if (retries < 0) throw new IllegalArgumentException(\"retries must be >= 0\");","typeGuard":"boolean validRetries = retries >= 0;","tryCatchPattern":"try { managementService.setJobRetries(jobId, retries); } catch (FlowableIllegalArgumentException e) { log.error(\"Invalid retries value: {}\", e.getMessage()); }","preventionTips":["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"],"tags":["flowable","invalid-argument-value","job-retries","out-of-range"],"backgroundTag":"invalid-argument-value","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T16:17:23.245Z"}