{"record":{"id":"9b9020c4d8d71512","repo":"provectus/kafka-ui","slug":"dynamic-file-path-is-a-directory-but-should-be-a","errorCode":null,"errorMessage":"Dynamic file path is a directory, but should be a file path","messagePattern":"Dynamic file path is a directory, but should be a file path","errorType":"validation","errorClass":"ValidationException","httpStatus":400,"severity":"error","filePath":"kafka-ui-api/src/main/java/com/provectus/kafka/ui/util/DynamicConfigOperations.java","lineNumber":174,"sourceCode":"    if (!filteringGroovyEnabled()) {\n      throw new ValidationException(\n              \"Groovy filters is not allowed. \"\n                      + \"Set filtering.groovy.enabled property to 'true' to enabled it.\");\n    }\n  }\n\n  private void checkIfDynamicConfigEnabled() {\n    if (!dynamicConfigEnabled()) {\n      throw new ValidationException(\n          \"Dynamic config change is not allowed. \"\n              + \"Set dynamic.config.enabled property to 'true' to enabled it.\");\n    }\n  }\n\n  @SneakyThrows\n  private void writeYamlToFile(String yaml, Path path) {\n    if (Files.isDirectory(path)) {\n      throw new ValidationException(\"Dynamic file path is a directory, but should be a file path\");\n    }\n    if (!Files.exists(path.getParent())) {\n      Files.createDirectories(path.getParent());\n    }\n    if (Files.exists(path) && !Files.isWritable(path)) {\n      throw new ValidationException(\"File already exists and is not writable\");\n    }\n    try {\n      Files.writeString(\n          path,\n          yaml,\n          StandardOpenOption.CREATE,\n          StandardOpenOption.WRITE,\n          StandardOpenOption.TRUNCATE_EXISTING // to override existing file\n      );\n    } catch (IOException e) {\n      throw new ValidationException(\"Error writing to \" + path, e);\n    }","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/provectus/kafka-ui/blob/83b5a60cc08501b570a0c4d0b4cdfceb1b88d6b7/kafka-ui-api/src/main/java/com/provectus/kafka/ui/util/DynamicConfigOperations.java#L156-L192","documentation":"writeYamlToFile() persists the serialized dynamic config YAML to the path configured by `dynamic.config.path`. Before writing it checks Files.isDirectory(path); if the configured path points at an existing directory it throws this ValidationException, since a directory cannot be used as the config file.","triggerScenarios":"`dynamic.config.path` (or DYNAMIC_CONFIG_PATH env var) set to a directory such as `/etc/kafka-ui/` or `/tmp` instead of a full file path like `/etc/kafka-ui/application-config.yml`; persist() then calls writeYamlToFile and fails.","commonSituations":"Mounting a volume directory and pointing the property at the mount root; dropping the filename when templating the value in Helm/Kubernetes manifests.","solutions":["Change dynamic.config.path to a full file path inside an existing directory (e.g. /etc/kafka-ui/application-config.yml)","Restart kafka-ui with the corrected value","If a directory was mounted for this purpose, keep the directory mount but point the property at a file name inside it"],"exampleFix":"// before\ndynamic:\n  config:\n    path: /etc/kafka-ui/\n// after\ndynamic:\n  config:\n    path: /etc/kafka-ui/application-config.yml","handlingStrategy":"validation","validationCode":"Path p = Path.of(configPath);\nif (Files.isDirectory(p)) {\n  throw new IllegalArgumentException(\"dynamic.config.path must be a file path, not a directory: \" + configPath);\n}","typeGuard":null,"tryCatchPattern":"try {\n  dynamicConfigOperations.persist(props);\n} catch (ValidationException e) {\n  if (e.getMessage().startsWith(\"Dynamic file path\")) {\n    // fix the configured path and retry\n  }\n}","preventionTips":["Always set dynamic.config.path to a full filename, not a directory","Validate the path in a startup/init container","Use helm template checks to assert the value ends with .yml/.yaml"],"tags":["configuration","filesystem","dynamic-config"],"backgroundTag":"invalid-config-value","analyzedSha":"83b5a60cc08501b570a0c4d0b4cdfceb1b88d6b7","analyzedAt":"2026-09-08T04:35:39.002Z","contentChangedAt":"2026-09-08T04:35:39.002Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}