{"record":{"id":"4e03b4cc62317560","repo":"alibaba/spring-ai-alibaba","slug":"ttl-must-be-positive-or-1-no-expiration-got","errorCode":null,"errorMessage":"ttl must be positive or -1 (no expiration), got: ","messagePattern":"ttl must be positive or -1 \\(no expiration\\), got: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/redis/RedisSaver.java","lineNumber":474,"sourceCode":"\n\t\t/**\n\t\t * Sets the time-to-live (TTL) for all Redis keys managed by RedisSaver.\n\t\t * When set, checkpoint data, thread metadata, and reverse mappings will\n\t\t * automatically expire after the specified duration.\n\t\t * <p>\n\t\t * Default is -1 (no expiration), which preserves backward compatibility.\n\t\t *\n\t\t * @param ttl the time-to-live value, must be positive; -1 means no expiration\n\t\t * @param ttlUnit the time unit for ttl, must not be null\n\t\t * @return this builder\n\t\t * @throws IllegalArgumentException if ttlUnit is null or ttl is 0 or less than -1\n\t\t */\n\t\tpublic Builder ttl(long ttl, TimeUnit ttlUnit) {\n\t\t\tif (ttlUnit == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"ttlUnit cannot be null\");\n\t\t\t}\n\t\t\tif (ttl == 0 || ttl < -1) {\n\t\t\t\tthrow new IllegalArgumentException(\"ttl must be positive or -1 (no expiration), got: \" + ttl);\n\t\t\t}\n\t\t\tthis.ttl = ttl;\n\t\t\tthis.ttlUnit = ttlUnit;\n\t\t\treturn this;\n\t\t}\n\n\t\t/**\n\t\t * Builds a new RedisSaver instance.\n\t\t * @return a new RedisSaver instance\n\t\t * @throws IllegalArgumentException if redisson or stateSerializer is null\n\t\t */\n\t\tpublic RedisSaver build() {\n\t\t\tif (redisson == null) {\n\t\t\t\tthrow new IllegalArgumentException(\"redisson cannot be null\");\n\t\t\t}\n\t\t\tif (stateSerializer == null) {\n\t\t\t\tthis.stateSerializer = StateGraph.DEFAULT_JACKSON_SERIALIZER;\n\t\t\t}","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/checkpoint/savers/redis/RedisSaver.java#L456-L492","documentation":"RedisSaver.Builder.ttl(long, TimeUnit) only accepts a positive ttl or -1 meaning 'no expiration'. Passing 0 or any value less than -1 throws IllegalArgumentException with this message including the offending value.","triggerScenarios":"new RedisSaver.Builder().ttl(0, TimeUnit.SECONDS) or ttl(-5, TimeUnit.SECONDS) — typically when ttl is read from configuration that defaults to 0 or is computed to a negative value.","commonSituations":"Config property checkpoint.ttl=0 interpreted as 'forever' by the developer but rejected by the builder (they must use -1 for no expiration); arithmetic producing negative TTLs; unit tests with unset ttl fields defaulting to 0.","solutions":["Use -1 instead of 0 when you want checkpoints to never expire: ttl(-1, TimeUnit.SECONDS).","Clamp/validate the configured ttl before building: if (ttl == 0) ttl = -1; or reject non-positive config values at startup.","Pass a positive ttl (e.g. 3600 seconds) if checkpoints should actually expire."],"exampleFix":"// before\nRedisSaver saver = new RedisSaver.Builder().ttl(ttl, TimeUnit.SECONDS).build(); // ttl = 0\n// after\nlong effectiveTtl = (ttl == 0) ? -1 : ttl;\nRedisSaver saver = new RedisSaver.Builder().ttl(effectiveTtl, TimeUnit.SECONDS).build();","handlingStrategy":"validation","validationCode":"if (ttl == 0 || ttl < -1) {\n    throw new IllegalStateException(\"checkpoint ttl must be > 0 or -1 (no expiration), got: \" + ttl);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember -1 (not 0) means 'no expiration' in this builder.","Validate ttl in configuration binding (e.g. @Min/@Custom validator) before building the saver.","Normalize 0 from external config to -1 or a positive default at load time."],"tags":["redis","builder","validation","ttl"],"backgroundTag":"invalid-argument-value","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}