{"record":{"id":"39eacb4fca3bfe16","repo":"alibaba/Sentinel","slug":"parser-can-t-be-null","errorCode":null,"errorMessage":"parser can't be null","messagePattern":"parser can't be null","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sentinel-extension/sentinel-datasource-extension/src/main/java/com/alibaba/csp/sentinel/datasource/AbstractDataSource.java","lineNumber":36,"sourceCode":"import com.alibaba.csp.sentinel.property.DynamicSentinelProperty;\nimport com.alibaba.csp.sentinel.property.SentinelProperty;\n\n/**\n * The abstract readable data source provides basic functionality for loading and parsing config.\n *\n * @param <S> source data type\n * @param <T> target data type\n * @author Carpenter Lee\n * @author Eric Zhao\n */\npublic abstract class AbstractDataSource<S, T> implements ReadableDataSource<S, T> {\n\n    protected final Converter<S, T> parser;\n    protected final SentinelProperty<T> property;\n\n    public AbstractDataSource(Converter<S, T> parser) {\n        if (parser == null) {\n            throw new IllegalArgumentException(\"parser can't be null\");\n        }\n        this.parser = parser;\n        this.property = new DynamicSentinelProperty<T>();\n    }\n\n    @Override\n    public T loadConfig() throws Exception {\n        return loadConfig(readSource());\n    }\n\n    public T loadConfig(S conf) throws Exception {\n        T value = parser.convert(conf);\n        return value;\n    }\n\n    @Override\n    public SentinelProperty<T> getProperty() {\n        return property;","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/alibaba/Sentinel/blob/a3f40ba8e900c8489bd520274739f17235a7721c/sentinel-extension/sentinel-datasource-extension/src/main/java/com/alibaba/csp/sentinel/datasource/AbstractDataSource.java#L18-L54","documentation":"AbstractDataSource is the base of all Sentinel readable data sources (file, Nacos, Apollo, Consul, zk, etc.). It needs a Converter<S,T> to turn raw source data into rule objects and throws IllegalArgumentException if the parser is null — without it loadConfig(conf) could not convert anything.","triggerScenarios":"Constructing any datasource subclass with a null Converter, e.g. new FileRefreshableDataSource(file, null) or new NacosDataSource(properties, groupId, dataId, null).","commonSituations":"Passing a converter variable that was never initialized; using a JSON converter factory method that returned null; copy-pasting datasource examples while omitting the converter lambda.","solutions":["Supply a real Converter, typically converter = s -> JSON.parseObject(s, new TypeReference<List<FlowRule>>() {}).","If the converter comes from a factory/helper, check it cannot return null and fail there with a clearer error.","Remove null 'placeholder' converters from scaffolding code before shipping."],"exampleFix":"// before\nReadableDataSource<String, List<FlowRule>> ds =\n    new FileRefreshableDataSource<>(file, null);\n\n// after\nConverter<String, List<FlowRule>> parser = s ->\n    JSON.parseObject(s, new TypeReference<List<FlowRule>>() {});\nReadableDataSource<String, List<FlowRule>> ds =\n    new FileRefreshableDataSource<>(file, parser);","handlingStrategy":"validation","validationCode":"Converter<String, List<FlowRule>> parser = s ->\n    JSON.parseObject(s, new TypeReference<List<FlowRule>>() {});\nObjects.requireNonNull(parser, \"config parser is required\");\nnew FileRefreshableDataSource<>(file, parser, charset);","typeGuard":"boolean hasParser(Converter<?, ?> parser) {\n    return parser != null;\n}","tryCatchPattern":null,"preventionTips":["Create the converter inline at the construction site — never thread an uninitialized field into a datasource.","Centralize converter creation in one factory per rule type."],"tags":["sentinel","datasource","converter","constructor-validation"],"backgroundTag":null,"analyzedSha":"a3f40ba8e900c8489bd520274739f17235a7721c","analyzedAt":"2026-08-14T11:10:30.678Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}