{"record":{"id":"e0f13d5bfc5d6c45","repo":"quarkusio/quarkus","slug":"limit-must-be-a-positive-integer","errorCode":null,"errorMessage":"Limit must be a positive integer: ","messagePattern":"Limit must be a positive integer: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/signals/runtime/src/main/java/io/quarkus/signals/runtime/impl/ConcurrencyLimiter.java","lineNumber":20,"sourceCode":"\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentLinkedQueue;\nimport java.util.concurrent.atomic.AtomicInteger;\nimport java.util.function.Consumer;\n\nimport org.jboss.logging.Logger;\n\nclass ConcurrencyLimiter {\n\n    private static final Logger LOG = Logger.getLogger(ConcurrencyLimiter.class);\n\n    private final int limit;\n    private final AtomicInteger running;\n    private final Queue<Action> queue;\n\n    ConcurrencyLimiter(int limit) {\n        if (limit <= 0) {\n            throw new IllegalArgumentException(\n                    \"Limit must be a positive integer: \" + limit);\n        }\n        this.limit = limit;\n        this.running = new AtomicInteger();\n        this.queue = new ConcurrentLinkedQueue<>();\n    }\n\n    void run(Runnable task, Consumer<Throwable> onError) {\n        queue.offer(new Action(task, onError));\n        LOG.debugf(\"Queue action [running=%s, limit=%s]\", running, limit);\n        tryDrain();\n    }\n\n    /**\n     * Signals that a previously started action has finished. Must be called exactly once per started action, and must not be\n     * called synchronously inside the action's {@link Runnable#run()} — doing so causes recursive {@link #tryDrain()} calls\n     * whose stack depth equals the queue size.\n     */","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/signals/runtime/src/main/java/io/quarkus/signals/runtime/impl/ConcurrencyLimiter.java#L2-L38","documentation":"ConcurrencyLimiter throttles concurrent receiver executions with a bounded permit count. A limit of zero or negative would deadlock every invocation, so the constructor validates it eagerly and throws IllegalArgumentException.","triggerScenarios":"Constructing ConcurrencyLimiter with limit <= 0, typically from a misconfigured limit property (0, negative, or a failed parse defaulting oddly).","commonSituations":"Setting a config value like quarkus.signal...limit=0 to mean 'unlimited' (unsupported) or typos such as '-1'.","solutions":["Set the configured limit to a positive integer (>= 1).","Remove the config override to fall back to the default limit.","If you intended unlimited concurrency, use the non-limited executor instead of a 0 limit."],"exampleFix":"// before\nquarkus.signal.concurrency-limit=0\n\n// after\nquarkus.signal.concurrency-limit=10","handlingStrategy":"validation","validationCode":"int limit = Integer.parseInt(cfg.limit());\nif (limit <= 0) throw new IllegalArgumentException(\"concurrency limit must be positive, got \" + limit);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never configure 0 or negative limits expecting 'unlimited'.","Validate config in tests with @ConfigMapping defaults.","Document the accepted range for the limit property."],"tags":["configuration","validation","concurrency","signals"],"backgroundTag":"invalid-config-value","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}