{"record":{"id":"7f6e051efb7cc31f","repo":"binarywang/WxJava","slug":"parameter-leasemilliseconds-must-grate-then-0","errorCode":null,"errorMessage":"Parameter 'leaseMilliseconds' must grate then 0: {}","messagePattern":"Parameter 'leaseMilliseconds' must grate then 0: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"weixin-java-common/src/main/java/me/chanjar/weixin/common/util/locks/RedisTemplateSimpleDistributedLock.java","lineNumber":36,"sourceCode":" */\npublic class RedisTemplateSimpleDistributedLock implements Lock {\n\n  @Getter\n  private final StringRedisTemplate redisTemplate;\n  @Getter\n  private final String key;\n  @Getter\n  private final int leaseMilliseconds;\n\n  private final ThreadLocal<String> valueThreadLocal = new ThreadLocal<>();\n\n  public RedisTemplateSimpleDistributedLock( StringRedisTemplate redisTemplate, int leaseMilliseconds) {\n    this(redisTemplate, \"lock:\" + UUID.randomUUID().toString(), leaseMilliseconds);\n  }\n\n  public RedisTemplateSimpleDistributedLock( StringRedisTemplate redisTemplate,  String key, int leaseMilliseconds) {\n    if (leaseMilliseconds <= 0) {\n      throw new IllegalArgumentException(\"Parameter 'leaseMilliseconds' must grate then 0: \" + leaseMilliseconds);\n    }\n    this.redisTemplate = redisTemplate;\n    this.key = key;\n    this.leaseMilliseconds = leaseMilliseconds;\n  }\n\n  @Override\n  public void lock() {\n    boolean interrupted = false;\n    while (!tryLock()) {\n      try {\n        Thread.sleep(1000);\n      } catch (InterruptedException e) {\n        interrupted = true;\n      }\n    }\n    if (interrupted) {\n      Thread.currentThread().interrupt();","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/binarywang/WxJava/blob/1c43293a3c2c9d7e91304b6d037fb017f680d0c6/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/locks/RedisTemplateSimpleDistributedLock.java#L18-L54","documentation":"Thrown by the RedisTemplateSimpleDistributedLock constructor when leaseMilliseconds <= 0. The lease is used as the Redis key TTL (expire), so a non-positive value would create a lock that never expires or fails to set; the constructor rejects it up front with IllegalArgumentException. (Note the message typo 'grate' meaning 'greater'.)","triggerScenarios":"Constructing the lock with a zero or negative leaseMilliseconds, often from misconfigured properties, a default of 0, or an arithmetic expression that underflows.","commonSituations":"Spring @Value property missing so it defaults to 0; passing a configured millis that was divided/rounded to 0; copy-paste of a seconds value into a millis parameter.","solutions":["Set leaseMilliseconds to a positive value greater than the expected hold time (e.g. 30000).","Validate the configured value at application startup and fail fast with a clear message.","Make sure units match (milliseconds here, not seconds)."],"exampleFix":"// before\nnew RedisTemplateSimpleDistributedLock(template, 0);\n// after\nnew RedisTemplateSimpleDistributedLock(template, 30000);","handlingStrategy":"validation","validationCode":"int lease = configuredLeaseMillis; // from config\nif (lease <= 0) throw new IllegalStateException(\"leaseMilliseconds must be > 0\");\nnew RedisTemplateSimpleDistributedLock(template, lease);","typeGuard":"static boolean validLease(int ms) { return ms > 0; }","tryCatchPattern":"null","preventionTips":["Provide an explicit positive leaseMillis in configuration.","Validate the value at startup, not just at construction.","Remember the unit is milliseconds, not seconds."],"tags":["redis","distributed-lock","validation","configuration"],"backgroundTag":null,"analyzedSha":"1c43293a3c2c9d7e91304b6d037fb017f680d0c6","analyzedAt":"2026-08-14T02:29:11.060Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}