alibaba/Sentinel · error · IllegalArgumentException

recommendRefreshMs must > 0, but {} get

Error message

recommendRefreshMs must > 0, but {} get

What it means

AutoRefreshDataSource schedules periodic readSource()+loadConfig() refreshes every recommendRefreshMs. The constructor validates recommendRefreshMs > 0 because scheduleAtFixedRate with a non-positive period would throw its own IllegalArgumentException immediately inside the timer setup.

Source

Thrown at sentinel-extension/sentinel-datasource-extension/src/main/java/com/alibaba/csp/sentinel/datasource/AutoRefreshDataSource.java:45

 *
 * @param <S> source data type
 * @param <T> target data type
 * @author Carpenter Lee
 */
public abstract class AutoRefreshDataSource<S, T> extends AbstractDataSource<S, T> {

    private ScheduledExecutorService service;
    protected long recommendRefreshMs = 3000;

    public AutoRefreshDataSource(Converter<S, T> configParser) {
        super(configParser);
        startTimerService();
    }

    public AutoRefreshDataSource(Converter<S, T> configParser, final long recommendRefreshMs) {
        super(configParser);
        if (recommendRefreshMs <= 0) {
            throw new IllegalArgumentException("recommendRefreshMs must > 0, but " + recommendRefreshMs + " get");
        }
        this.recommendRefreshMs = recommendRefreshMs;
        startTimerService();
    }

    @SuppressWarnings("PMD.ThreadPoolCreationRule")
    private void startTimerService() {
        service = Executors.newScheduledThreadPool(1,
            new NamedThreadFactory("sentinel-datasource-auto-refresh-task", true));
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    if (!isModified()) {
                        return;
                    }
                    T newValue = loadConfig();
                    getProperty().updateValue(newValue);

View on GitHub (pinned to a3f40ba8e9)

Solutions

  1. Set recommendRefreshMs to a positive millisecond value (default in FileRefreshableDataSource is DEFAULT_REFRESH_MS = 3000).
  2. If you intended to disable auto refresh, use a plain (non-refreshing) datasource such as FileInJarReadableDataSource's base or ReadableDataSource directly instead of 0.
  3. Check the property source feeding the interval and give it a sane default when absent.

Example fix

// before
new FileRefreshableDataSource<>(file, parser, 0, 1024 * 1024, charset);

// after
new FileRefreshableDataSource<>(file, parser, 3000, 1024 * 1024, charset);
// or omit refresh: new FileRefreshableDataSource<>(file, parser, charset);
Defensive patterns

Strategy: validation

Validate before calling

long refreshMs = props.getProperty("refreshMs") == null
    ? 3000L
    : Long.parseLong(props.getProperty("refreshMs"));
if (refreshMs <= 0) {
    throw new ConfigurationException("refreshMs must be > 0, got " + refreshMs);
}
new FileRefreshableDataSource<>(file, parser, refreshMs, bufSize, charset);

Prevention

When it happens

Trigger: new AutoRefreshDataSource(parser, recommendRefreshMs) or any subclass constructor (e.g. new FileRefreshableDataSource(file, parser, 0, bufSize, charset)) with refreshMs <= 0.

Common situations: A refresh-interval property set to 0 (sometimes meant as 'disable refresh' — not supported here); unit mix-ups (passing a seconds value of 0/1 where ms expected after a refactor); property placeholders that resolve to 0 when undefined.

Related errors


AI-assisted analysis of alibaba/Sentinel@a3f40ba8e9 (2026-08-14). Data as JSON: /api/errors/d6a0b4d8c79d9879. Report an issue: GitHub.