{"record":{"id":"52c94d5a9cdb70f9","repo":"quarkusio/quarkus","slug":"timeout-must-not-be-null","errorCode":null,"errorMessage":"`timeout` must not be `null`","messagePattern":"`timeout` must not be `null`","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/string/GetExArgs.java","lineNumber":43,"sourceCode":"     * Set the specified expire time, in seconds.\n     *\n     * @param timeout expire time in seconds.\n     * @return the current {@code GetExArgs}\n     */\n    public GetExArgs ex(long timeout) {\n        this.ex = timeout;\n        return this;\n    }\n\n    /**\n     * Sets the expiration.\n     *\n     * @param timeout expire time in seconds.\n     * @return the current {@code GetExArgs}\n     */\n    public GetExArgs ex(Duration timeout) {\n        if (timeout == null) {\n            throw new IllegalArgumentException(\"`timeout` must not be `null`\");\n        }\n        return ex(timeout.toMillis() / 1000);\n    }\n\n    /**\n     * Sets the expiration time\n     *\n     * @param timestamp the timestamp\n     * @return the current {@code GetExArgs}\n     */\n    public GetExArgs exAt(long timestamp) {\n        this.exAt = timestamp;\n        return this;\n    }\n\n    /**\n     * Sets the expiration time\n     *","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/string/GetExArgs.java#L25-L61","documentation":"The deprecated GetExArgs.ex(Duration) converts the duration to seconds for the GETEX EX option; it requires a non-null Duration. Passing null would otherwise produce a NullPointerException later, so the method fails fast with this IllegalArgumentException.","triggerScenarios":"Calling GetExArgs.ex((Duration) null) directly, or passing a Duration variable that resolved to null (e.g. from an Optional.get()/config lookup that was absent) into ex(Duration) when building args for a getex command.","commonSituations":"Expiration durations pulled from configuration or environment that are unset/null; optional TTL values that were not defaulted before constructing the args.","solutions":["Pass a concrete non-null Duration, e.g. GetExArgs.ex(Duration.ofSeconds(60))","If the TTL is optional, guard with a null check and skip the getex or use persist()/a default TTL","Prefer the long overload ex(long) with a computed value when the source may be null"],"exampleFix":"// before\nDuration ttl = config.get(\"ttl\", Duration.class); // may be null\nargs.ex(ttl);\n// after\nDuration ttl = config.get(\"ttl\", Duration.class);\nif (ttl != null) {\n    args.ex(ttl);\n}","handlingStrategy":"validation","validationCode":"if (timeout == null) {\n    throw new IllegalArgumentException(\"TTL must be provided for GETEX ex()\");\n}","typeGuard":"boolean hasTtl(Duration d) {\n    return d != null && !d.isNegative() && !d.isZero();\n}","tryCatchPattern":"try {\n    redis.string().getex(key, new GetExArgs().ex(ttl));\n} catch (IllegalArgumentException e) {\n    log.warn(\"GETEX skipped: \" + e.getMessage());\n}","preventionTips":["Null-check TTL values sourced from config or Optional before building args","Provide a default TTL instead of passing null","Prefer Duration typed configuration so absence is explicit"],"tags":["redis","getex","null-check","invalid-arguments"],"backgroundTag":"null-argument","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"}