{"record":{"id":"066ca386454b5ba2","repo":"alibaba/Sentinel","slug":"bad-file","errorCode":null,"errorMessage":"Bad file","messagePattern":"Bad file","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sentinel-extension/sentinel-datasource-extension/src/main/java/com/alibaba/csp/sentinel/datasource/FileWritableDataSource.java","lineNumber":53,"sourceCode":"    private static final Charset DEFAULT_CHARSET = Charset.forName(\"UTF-8\");\n\n    private final Converter<T, String> configEncoder;\n    private final File file;\n    private final Charset charset;\n\n    private final Lock lock = new ReentrantLock(true);\n\n    public FileWritableDataSource(String filePath, Converter<T, String> configEncoder) {\n        this(new File(filePath), configEncoder);\n    }\n\n    public FileWritableDataSource(File file, Converter<T, String> configEncoder) {\n        this(file, configEncoder, DEFAULT_CHARSET);\n    }\n\n    public FileWritableDataSource(File file, Converter<T, String> configEncoder, Charset charset) {\n        if (file == null || file.isDirectory()) {\n            throw new IllegalArgumentException(\"Bad file\");\n        }\n        if (configEncoder == null) {\n            throw new IllegalArgumentException(\"Config encoder cannot be null\");\n        }\n        if (charset == null) {\n            throw new IllegalArgumentException(\"Charset cannot be null\");\n        }\n        this.configEncoder = configEncoder;\n        this.file = file;\n        this.charset = charset;\n    }\n\n    @Override\n    public void write(T value) throws Exception {\n        lock.lock();\n        try {\n            String convertResult = configEncoder.convert(value);\n            FileOutputStream outputStream = null;","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/alibaba/Sentinel/blob/a3f40ba8e900c8489bd520274739f17235a7721c/sentinel-extension/sentinel-datasource-extension/src/main/java/com/alibaba/csp/sentinel/datasource/FileWritableDataSource.java#L35-L71","documentation":"Thrown by the FileWritableDataSource constructor when the given File is null or is a directory. This writable data source serializes config back into a single file (e.g. for the Sentinel dashboard to persist rules), so a directory target is invalid.","triggerScenarios":"new FileWritableDataSource(filePath, encoder) with a path that resolves to a directory; passing a null File after a failed path lookup; using the same directory path that works for a file-based reader without appending the file name.","commonSituations":"Configuring rule persistence with a path like /opt/sentinel/rules/ (directory) instead of /opt/sentinel/rules/flow-rule.json; path property typo; code that builds the File conditionally and passes null on the untested branch.","solutions":["Point the data source at a concrete file path ending in a file name (e.g. .../flow-rule.json).","Assert the path is non-null before constructing; fail with the name of the missing property/config key.","If the parent directory may not exist yet, create it with Files.createDirectories(parent) before writing (write() itself will fail otherwise)."],"exampleFix":"// before\nnew FileWritableDataSource<>(\"/opt/sentinel/rules/\", encoder);\n\n// after\nPath p = Paths.get(\"/opt/sentinel/rules/flow-rule.json\");\nFiles.createDirectories(p.getParent());\nnew FileWritableDataSource<>(p.toFile(), encoder);","handlingStrategy":"validation","validationCode":"if (file == null || file.isDirectory()) {\n    throw new IllegalArgumentException(\"writable rule path must be a file: \" + path);\n}\nFiles.createDirectories(file.toPath().getParent());\nnew FileWritableDataSource<>(file, encoder, charset);","typeGuard":null,"tryCatchPattern":"try {\n    writable = new FileWritableDataSource<>(file, encoder, charset);\n} catch (IllegalArgumentException e) {\n    throw new IllegalStateException(\"Invalid FileWritableDataSource config for path: \" + path, e);\n}","preventionTips":["Always configure the full file path including file name for writable rule persistence.","Create the parent directory at startup to avoid later write failures."],"tags":["sentinel","datasource","file","writable-datasource","constructor-validation","java"],"backgroundTag":null,"analyzedSha":"a3f40ba8e900c8489bd520274739f17235a7721c","analyzedAt":"2026-08-14T11:10:30.678Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}