alibaba/Sentinel · error · IllegalArgumentException

charset can't be null

Error message

charset can't be null

What it means

Thrown by the FileRefreshableDataSource constructor when the Charset argument is null. The charset is used to decode raw file bytes into the String handed to the config parser, so a null charset would cause an NPE on every read; Sentinel rejects it up front instead.

Source

Thrown at sentinel-extension/sentinel-datasource-extension/src/main/java/com/alibaba/csp/sentinel/datasource/FileRefreshableDataSource.java:87

        this(file, configParser, DEFAULT_REFRESH_MS, bufSize, DEFAULT_CHAR_SET);
    }

    public FileRefreshableDataSource(File file, Converter<String, T> configParser, Charset charset)
        throws FileNotFoundException {
        this(file, configParser, DEFAULT_REFRESH_MS, DEFAULT_BUF_SIZE, charset);
    }

    public FileRefreshableDataSource(File file, Converter<String, T> configParser, long recommendRefreshMs, int bufSize,
                                     Charset charset) throws FileNotFoundException {
        super(configParser, recommendRefreshMs);
        if (bufSize <= 0 || bufSize > MAX_SIZE) {
            throw new IllegalArgumentException("bufSize must between (0, " + MAX_SIZE + "], but " + bufSize + " get");
        }
        if (file == null || file.isDirectory()) {
            throw new IllegalArgumentException("File can't be null or a directory");
        }
        if (charset == null) {
            throw new IllegalArgumentException("charset can't be null");
        }
        this.buf = new byte[bufSize];
        this.file = file;
        this.charset = charset;
        // If the file does not exist, the last modified will be 0.
        this.lastModified = file.lastModified();
        firstLoad();
    }

    private void firstLoad() {
        try {
            T newValue = loadConfig();
            getProperty().updateValue(newValue);
        } catch (Throwable e) {
            RecordLog.info("loadConfig exception", e);
        }
    }

View on GitHub (pinned to a3f40ba8e9)

Solutions

  1. Pass an explicit charset, e.g. Charset.forName("UTF-8") or StandardCharsets.UTF_8.
  2. If the charset is optional in your code, default it before calling the constructor: charset = charset == null ? StandardCharsets.UTF_8 : charset.
  3. Use a constructor overload that does not take a charset if you are happy with the library default.

Example fix

// before
Charset cs = null; // from config, never set
new FileRefreshableDataSource<>(file, parser, 3000, 1024 * 1024, cs);

// after
Charset cs = Optional.ofNullable(configCharset).orElse(StandardCharsets.UTF_8);
new FileRefreshableDataSource<>(file, parser, 3000, 1024 * 1024, cs);
Defensive patterns

Strategy: validation

Validate before calling

Charset cs = (charset == null) ? StandardCharsets.UTF_8 : charset;
new FileRefreshableDataSource<>(file, parser, refreshMs, bufSize, cs);

Try / catch

try {
    new FileRefreshableDataSource<>(file, parser, cs);
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("charset must be provided for file data source", e);
}

Prevention

When it happens

Trigger: Calling the 3-arg constructor new FileRefreshableDataSource(file, parser, (Charset) null), or the 5-arg constructor with a null charset variable (common when charset is injected/optional and defaults were not applied).

Common situations: Passing a charset loaded from config that was never set; refactoring code that previously used a constructor without a charset parameter and accidentally forwarding null; test code that omits the charset argument.

Related errors


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