{"record":{"id":"5159e51a3d2e8d23","repo":"quarkusio/quarkus","slug":"cannot-combine-idle-and-time","errorCode":null,"errorMessage":"Cannot combine `IDLE` and `TIME`","messagePattern":"Cannot combine `IDLE` and `TIME`","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/stream/XClaimArgs.java","lineNumber":107,"sourceCode":"     * Sets the last id of the message to claim.\n     *\n     * @param lastId the last id, must not be {@code null}\n     * @return the current {@code XClaimArgs}\n     */\n    public XClaimArgs lastId(String lastId) {\n        this.lastId = lastId;\n        return this;\n    }\n\n    @Override\n    public List<Object> toArgs() {\n        List<Object> args = new ArrayList<>();\n\n        if (idle != null) {\n            args.add(\"IDLE\");\n            args.add(Long.toString(idle.toMillis()));\n            if (time > 0) {\n                throw new IllegalStateException(\"Cannot combine `IDLE` and `TIME`\");\n            }\n        }\n\n        if (time > 0) {\n            args.add(\"TIME\");\n            args.add(Long.toString(time));\n        }\n\n        if (retryCount > 0) {\n            args.add(\"RETRYCOUNT\");\n            args.add(Integer.toString(retryCount));\n        }\n\n        if (force) {\n            args.add(\"FORCE\");\n        }\n\n        if (justId) {","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/stream/XClaimArgs.java#L89-L125","documentation":"XCLAIM can set the delivery time of claimed messages either as a relative IDLE (milliseconds since now) or an absolute TIME (unix ms), but not both. XClaimArgs.toArgs() throws IllegalStateException when idle was set and time > 0 is also present, as the two are redundant/contradictory.","triggerScenarios":"Calling xclaimArgs().idle(Duration.ofSeconds(1)) and .time(epochMs) on the same instance; or time defaulting to a positive value while idle is also set.","commonSituations":"Config exposing both 'idle' and 'time' options and both being applied; migrating code from TIME-based to IDLE-based claims leaving the old field set; builder reuse.","solutions":["Keep only one: use .idle(Duration) for relative delay or .time(long) for absolute timestamp","Set the unused field to 0/null before building args","Derive one from the other if both inputs exist (e.g. idle = time - now) and set only idle"],"exampleFix":"// before\nXClaimArgs args = new XClaimArgs().idle(Duration.ofSeconds(1)).time(System.currentTimeMillis());\n// after\nXClaimArgs args = new XClaimArgs().idle(Duration.ofSeconds(1));","handlingStrategy":"validation","validationCode":"if (idle != null && time > 0) throw new IllegalArgumentException(\"XCLAIM accepts IDLE or TIME, not both\");","typeGuard":null,"tryCatchPattern":"try {\n    stream.xclaim(key, group, consumer, minIdle, ids, args);\n} catch (IllegalStateException e) {\n    // rebuild XClaimArgs with only idle or only time\n}","preventionTips":["Choose one time model (relative IDLE vs absolute TIME) per use case","Convert between them explicitly: idle = Duration.ofMillis(time - now)","Zero-out the unused option when loading settings from config"],"tags":["redis","streams","mutually-exclusive-options","xclaim"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}