{"record":{"id":"01a6f73dc01bad18","repo":"grpc/grpc-java","slug":"refresh-interval-must-be-greater-than-0","errorCode":null,"errorMessage":"Refresh interval must be greater than 0","messagePattern":"Refresh interval must be greater than 0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"authz/src/main/java/io/grpc/authz/FileWatcherAuthorizationServerInterceptor.java","lineNumber":88,"sourceCode":"    internalAuthzServerInterceptor = AuthorizationServerInterceptor.create(policyContents);\n  }\n\n  /** \n   * Policy is reloaded periodically as per the provided refresh interval. Unlike the\n   * constructor, exception thrown during reload will be caught and logged and the\n   * previous AuthorizationServerInterceptor will be used to make authorization\n   * decisions.\n   * \n   * @param period the period between successive file load executions.\n   * @param unit the time unit for period parameter\n   * @param executor the execute service we use to read and update authorization policy\n   * @return an object that caller should close when the file refreshes are not needed\n   */\n  public Closeable scheduleRefreshes(\n      long period, TimeUnit unit, ScheduledExecutorService executor) throws IOException {\n    checkNotNull(executor, \"scheduledExecutorService\");\n    if (period <= 0) {\n      throw new IllegalArgumentException(\"Refresh interval must be greater than 0\");\n    }\n    final ScheduledFuture<?> future = \n        executor.scheduleWithFixedDelay(new Runnable() {\n          @Override\n          public void run() {\n            try {\n              updateInternalInterceptor();\n            } catch (Exception e) {\n              logger.log(Level.WARNING, \"Authorization Policy file reload failed\", e);\n            }\n          }\n        }, period, period, unit);\n    return new Closeable() {\n      @Override public void close() {\n        future.cancel(false);\n      }\n    };\n  }","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/authz/src/main/java/io/grpc/authz/FileWatcherAuthorizationServerInterceptor.java#L70-L106","documentation":"FileWatcherAuthorizationServerInterceptor.scheduleRefreshes() schedules a file re-read with scheduleWithFixedDelay, which requires a positive period. A period <= 0 can never fire a sensible refresh loop, so the method throws IllegalArgumentException('Refresh interval must be greater than 0') before scheduling.","triggerScenarios":"Calling scheduleRefreshes(period, unit, executor) with period <= 0 — e.g. scheduleRefreshes(0, SECONDS, executor) or a negative value from misparsed config, or 0 as a 'poll immediately' attempt.","commonSituations":"Config value '0' meaning 'disable polling' being passed through instead of skipping the call; unit/time arithmetic bug producing 0 milliseconds; parsing an empty config string to 0.","solutions":["Pass a positive period, e.g. scheduleRefreshes(5, TimeUnit.SECONDS, executor)","Guard the call: only invoke scheduleRefreshes when the configured interval > 0; skip/disable polling otherwise","Fix config parsing so a missing/zero interval maps to a sane default (e.g. 10s) rather than 0"],"exampleFix":"// before\nwatcher.scheduleRefreshes(refreshIntervalSeconds, TimeUnit.SECONDS, executor);\n// after\nif (refreshIntervalSeconds > 0) {\n  watcher.scheduleRefreshes(refreshIntervalSeconds, TimeUnit.SECONDS, executor);\n}","handlingStrategy":"validation","validationCode":"if (periodMillis <= 0) {\n  periodMillis = TimeUnit.SECONDS.toMillis(10); // or skip scheduling\n}\nwatcher.scheduleRefreshes(periodMillis, TimeUnit.MILLISECONDS, executor);","typeGuard":"static boolean isValidRefreshInterval(long period) { return period > 0; }","tryCatchPattern":"try {\n  closeable = watcher.scheduleRefreshes(period, unit, executor);\n} catch (IllegalArgumentException e) {\n  log.error(\"Invalid refresh interval: \" + e.getMessage());\n  closeable = null; // run without file watching\n}","preventionTips":["Never use 0 as a sentinel for 'disable polling'; skip the call instead","Clamp parsed config intervals to a positive minimum","Unit-test config parsing for interval values including 0 and negatives"],"tags":["grpc","authz","file-watcher","argument-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}