{"record":{"id":"540abd7bcf961dbc","repo":"alibaba/Sentinel","slug":"file-can-t-be-null-or-a-directory","errorCode":null,"errorMessage":"File can't be null or a directory","messagePattern":"File can't be null or a directory","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sentinel-extension/sentinel-datasource-extension/src/main/java/com/alibaba/csp/sentinel/datasource/FileRefreshableDataSource.java","lineNumber":84,"sourceCode":"\n    public FileRefreshableDataSource(File file, Converter<String, T> configParser, int bufSize)\n        throws FileNotFoundException {\n        this(file, configParser, DEFAULT_REFRESH_MS, bufSize, DEFAULT_CHAR_SET);\n    }\n\n    public FileRefreshableDataSource(File file, Converter<String, T> configParser, Charset charset)\n        throws FileNotFoundException {\n        this(file, configParser, DEFAULT_REFRESH_MS, DEFAULT_BUF_SIZE, charset);\n    }\n\n    public FileRefreshableDataSource(File file, Converter<String, T> configParser, long recommendRefreshMs, int bufSize,\n                                     Charset charset) throws FileNotFoundException {\n        super(configParser, recommendRefreshMs);\n        if (bufSize <= 0 || bufSize > MAX_SIZE) {\n            throw new IllegalArgumentException(\"bufSize must between (0, \" + MAX_SIZE + \"], but \" + bufSize + \" get\");\n        }\n        if (file == null || file.isDirectory()) {\n            throw new IllegalArgumentException(\"File can't be null or a directory\");\n        }\n        if (charset == null) {\n            throw new IllegalArgumentException(\"charset can't be null\");\n        }\n        this.buf = new byte[bufSize];\n        this.file = file;\n        this.charset = charset;\n        // If the file does not exist, the last modified will be 0.\n        this.lastModified = file.lastModified();\n        firstLoad();\n    }\n\n    private void firstLoad() {\n        try {\n            T newValue = loadConfig();\n            getProperty().updateValue(newValue);\n        } catch (Throwable e) {\n            RecordLog.info(\"loadConfig exception\", e);","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/alibaba/Sentinel/blob/a3f40ba8e900c8489bd520274739f17235a7721c/sentinel-extension/sentinel-datasource-extension/src/main/java/com/alibaba/csp/sentinel/datasource/FileRefreshableDataSource.java#L66-L102","documentation":"Thrown by the FileRefreshableDataSource constructor when the supplied java.io.File is null or points to a directory. FileRefreshableDataSource polls a regular file for Sentinel rule/config content, so a directory or missing File object is an invalid data source target. The check runs after the bufSize check but before any field assignment, so the data source is never partially constructed.","triggerScenarios":"Calling new FileRefreshableDataSource(file, parser, charset) (or the 5-arg overload) with file == null, or with a File whose isDirectory() returns true (e.g. passing a config directory instead of the rules file itself).","commonSituations":"Pointing the data source at a directory like /etc/sentinel/ instead of /etc/sentinel/flow-rules.json; building the File from a misconfigured system property or environment variable that resolves to null/empty and the code does new File(nullValue) or passes null; copy-pasting an example where the path is a folder containing multiple rule files.","solutions":["Pass the path of the actual rule FILE, not its parent directory (e.g. /data/sentinel/flow-rule.json, not /data/sentinel/).","If the path comes from configuration, log and validate it before constructing the File so a null/blank value fails with your own clear message.","If you need to load several files, create one FileRefreshableDataSource per file.","Wrap construction in try/catch IllegalArgumentException to fail fast with context (which property/variable supplied the bad path)."],"exampleFix":"// before\nFile dir = new File(System.getProperty(\"sentinel.rules.dir\"));\nnew FileRefreshableDataSource<>(dir, parser, charset);\n\n// after\nFile file = new File(Objects.requireNonNull(\n    System.getProperty(\"sentinel.rules.file\"), \"sentinel.rules.file must be set\"));\nnew FileRefreshableDataSource<>(file, parser, charset);","handlingStrategy":"validation","validationCode":"// before constructing\nif (file == null || file.isDirectory()) {\n    throw new IllegalArgumentException(\"rule file path must point to a file: \" + path);\n}\nnew FileRefreshableDataSource<>(file, parser, charset);","typeGuard":null,"tryCatchPattern":"try {\n    dataSource = new FileRefreshableDataSource<>(file, parser, charset);\n} catch (IllegalArgumentException e) {\n    throw new IllegalStateException(\"Invalid FileRefreshableDataSource config for path: \" + path, e);\n}","preventionTips":["Derive the File from a single required property and validate it is a file at startup.","Never point the data source at a directory; create one data source per rule file."],"tags":["sentinel","datasource","file","constructor-validation","java"],"backgroundTag":null,"analyzedSha":"a3f40ba8e900c8489bd520274739f17235a7721c","analyzedAt":"2026-08-14T11:10:30.678Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}