{"record":{"id":"5200f9b747ca0bcb","repo":"quarkusio/quarkus","slug":"timestamp-must-not-be-null","errorCode":null,"errorMessage":"`timestamp` must not be `null`","messagePattern":"`timestamp` 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":67,"sourceCode":"     * 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     *\n     * @param timestamp the timestamp type: posix time in seconds.\n     * @return the current {@code GetExArgs}\n     */\n    public GetExArgs exAt(Instant timestamp) {\n        if (timestamp == null) {\n            throw new IllegalArgumentException(\"`timestamp` must not be `null`\");\n        }\n        exAt(timestamp.toEpochMilli() / 1000);\n        return this;\n    }\n\n    /**\n     * Set the specified expire time, in milliseconds.\n     *\n     * @param timeout expire time in milliseconds.\n     * @return the current {@code GetExArgs}\n     */\n    public GetExArgs px(long timeout) {\n        this.px = timeout;\n        return this;\n    }\n\n    /**\n     * Set the specified expire time, in milliseconds.","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/redis-client/runtime/src/main/java/io/quarkus/redis/datasource/string/GetExArgs.java#L49-L85","documentation":"GetExArgs.exAt(Instant) converts an Instant to POSIX seconds for the GETEX EXAT option; it requires a non-null Instant. Passing null would cause a downstream NPE, so the method fails fast with this IllegalArgumentException.","triggerScenarios":"Calling GetExArgs.exAt((Instant) null) — commonly with a computed timestamp variable that is null, e.g. Instant expiry = optional.map(...).orElse(null) followed by exAt(expiry) while building getex args.","commonSituations":"Optional expiration timestamps from scheduling/lookup logic returning null; uninitialized fields used as the expiry; refactors where a fallback Instant was dropped.","solutions":["Pass a concrete non-null Instant, e.g. exAt(Instant.now().plusSeconds(3600))","Guard with a null check and either skip exAt or use persist()/a relative ex(Duration) instead","Use Instant.now() or a defaulted value when the source timestamp is absent"],"exampleFix":"// before\nInstant expiry = null;\nargs.exAt(expiry);\n// after\nInstant expiry = computeExpiry();\nif (expiry == null) {\n    expiry = Instant.now().plusSeconds(3600);\n}\nargs.exAt(expiry);","handlingStrategy":"validation","validationCode":"if (timestamp == null) {\n    throw new IllegalArgumentException(\"Expiry timestamp must be provided for GETEX exAt()\");\n}","typeGuard":"boolean hasExpiry(Instant i) {\n    return i != null && i.isAfter(Instant.now());\n}","tryCatchPattern":"try {\n    redis.string().getex(key, new GetExArgs().exAt(expiry));\n} catch (IllegalArgumentException e) {\n    log.warn(\"GETEX skipped: \" + e.getMessage());\n}","preventionTips":["Ensure expiry computations never return null (use orElse with a sensible default)","Null-check computed Instant values before calling exAt","Validate the timestamp is in the future before sending EXAT"],"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-14T05:17:10.506Z"}