{"record":{"id":"22f54a0e19d6c48c","repo":"apache/cassandra","slug":"must-permit-at-least-one-attempt-attempts-value","errorCode":null,"errorMessage":"Must permit at least one attempt (attempts=${value} supplied)","messagePattern":"Must permit at least one attempt \\(attempts=(.+?) supplied\\)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/service/RetryStrategy.java","lineNumber":289,"sourceCode":"            while ((next = spec.lastIndexOf(',', end - 1)) >= 0)\n            {\n                int mid = spec.indexOf('=', next + 1);\n                if (mid <= next || mid >= end)\n                    throw new IllegalArgumentException(\"Invalid modifier specification: '\" + spec.substring(next, end) + \"'; expecting '=' for value assignment\");\n                String key = spec.substring(next + 1, mid).trim();\n                String value = spec.substring(mid + 1, end).trim();\n                switch (key)\n                {\n                    default: throw new IllegalArgumentException(\"Invalid modifier specification: unrecognised property '\" + key + '\\'');\n                    case \"retries\":\n                        retries = Integer.parseInt(value);\n                        if (retries < 0)\n                            throw new IllegalArgumentException(\"retries must be non-negative (retries=\" + value + \" supplied)\");\n                        break;\n                    case \"attempts\":\n                        retries = Integer.parseInt(value);\n                        if (retries < 0)\n                            throw new IllegalArgumentException(\"Must permit at least one attempt (attempts=\" + value + \" supplied)\");\n                        break;\n                    case \"rnd\":\n                        if (randomizer != null)\n                            throw new IllegalArgumentException(\"Randomizer already specified, cannot re-specify: \" + value);\n                        randomizer = parseWaitRandomizer(value);\n                        break;\n                }\n                end = next;\n            }\n            if (end != spec.length())\n                spec = spec.substring(0, end);\n        }\n\n        Matcher m = PARSE.matcher(spec);\n        if (!m.matches())\n            throw new IllegalArgumentException(\"Invalid specification: '\" + spec + \"'; does not match \" + PARSE);\n\n        long minMin = parseInMicros(m.group(\"minmin\"), 0);","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/service/RetryStrategy.java#L271-L307","documentation":"When parsing an 'attempts=<n>' modifier, RetryStrategy.parse() rejects negative values because at least one attempt must be permitted (the initial attempt counts). An IllegalArgumentException naming the supplied value is thrown.","triggerScenarios":"RetryStrategy.parse(spec, latencies) where spec ends with ',attempts=-2' or any negative integer. The value must be an int >= 0.","commonSituations":"Using attempts=-1 intending 'infinite attempts' (omit the modifier instead, since default retries is Integer.MAX_VALUE); automated config generators emitting negative placeholders.","solutions":["Set attempts to a non-negative integer (0 or more)","To allow unlimited attempts, omit the modifier rather than using a negative value","Use the 'retries=' modifier instead if you want to count retries rather than total attempts"],"exampleFix":"// before\nRetryStrategy.parse(\"100ms,attempts=-1\", latencies);\n// after\nRetryStrategy.parse(\"100ms\", latencies); // default permits effectively unlimited attempts","handlingStrategy":"validation","validationCode":"static int validateAttempts(String value) {\n    int attempts = Integer.parseInt(value.trim());\n    if (attempts < 0) throw new IllegalArgumentException(\"attempts must be >= 0, got \" + value);\n    return attempts;\n}","typeGuard":null,"tryCatchPattern":"try {\n    RetryStrategy strategy = RetryStrategy.parse(spec, latencies);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Must permit at least one attempt\")) {\n        LOG.warn(\"Invalid attempts in spec '{}', using default\", spec);\n        return RetryStrategy.parse(\"100ms\", latencies);\n    }\n    throw e;\n}","preventionTips":["Remember attempts counts total tries, so it must be >= 0","Omit the modifier for effectively unlimited attempts instead of -1","Clamp generated values with Math.max(0, attempts) before building the spec"],"tags":["configuration","parsing","value-range"],"backgroundTag":"value-out-of-range","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}