provectus/kafka-ui · error · ValidationException
File already exists and is not writable
Error message
File already exists and is not writable
What it means
After ensuring the target path is a file and creating parent directories, writeYamlToFile() checks that an existing config file is writable via Files.isWritable(). If the file exists but the process has no write permission on it, persisting the dynamic config throws this ValidationException.
Solutions
- chown/chmod the config file so the kafka-ui process user can write it (e.g. chmod u+w, chown to the container UID)
- Move dynamic.config.path to a writable volume instead of a read-only mount
- Ensure the container's securityContext allows writing to that path
Example fix
// before -r--r--r-- application-config.yml // after (shell) chmod u+w application-config.yml && chown kafka-ui:kafka-ui application-config.yml
Defensive patterns
Strategy: validation
Validate before calling
Path p = Path.of(configPath);
if (Files.exists(p) && !Files.isWritable(p)) {
throw new IllegalStateException("Config file exists but is not writable by this process");
} Try / catch
try {
dynamicConfigOperations.persist(props);
} catch (ValidationException e) {
if (e.getMessage().contains("not writable")) {
// chmod/chown or relocate to a writable volume
}
} Prevention
- Pre-create the config file with correct ownership in your deployment
- Avoid read-only mounts for the dynamic config path
- Match the file's UID/GID to the container's runtime user
When it happens
Trigger: dynamic.config.path points to an already-created file owned by another user or opened read-only (e.g. a read-only mounted secret/ConfigMap file) while kafka-ui tries to save new properties.
Common situations: Container runs as non-root but the config file was created by root; the file lives on a read-only volume mount; file permissions like 0444 set by a provisioning script.
Understand the failure class
Background: "Permission denied" / "Failed to write" file errors: why a library can't write its files to disk (EACCES, EPERM, ENOSPC) and how to fix them — this error's family across 43 libraries.
Related errors
- proto files directory not readable
- Dynamic file path is a directory, but should be a file path
- Error writing to
- Location does not exist
- No archive files were found
AI-assisted analysis of provectus/kafka-ui@83b5a60cc0 (2026-09-08).
Data as JSON: /api/errors/105d4ffb3d89f8cf.
Report an issue: GitHub.
Appendix: source
Thrown at kafka-ui-api/src/main/java/com/provectus/kafka/ui/util/DynamicConfigOperations.java:180
private void checkIfDynamicConfigEnabled() {
if (!dynamicConfigEnabled()) {
throw new ValidationException(
"Dynamic config change is not allowed. "
+ "Set dynamic.config.enabled property to 'true' to enabled it.");
}
}
@SneakyThrows
private void writeYamlToFile(String yaml, Path path) {
if (Files.isDirectory(path)) {
throw new ValidationException("Dynamic file path is a directory, but should be a file path");
}
if (!Files.exists(path.getParent())) {
Files.createDirectories(path.getParent());
}
if (Files.exists(path) && !Files.isWritable(path)) {
throw new ValidationException("File already exists and is not writable");
}
try {
Files.writeString(
path,
yaml,
StandardOpenOption.CREATE,
StandardOpenOption.WRITE,
StandardOpenOption.TRUNCATE_EXISTING // to override existing file
);
} catch (IOException e) {
throw new ValidationException("Error writing to " + path, e);
}
}
private String serializeToYaml(PropertiesStructure props) {
//representer, that skips fields with null values
Representer representer = new Representer(new DumperOptions()) {
@OverrideView on GitHub (pinned to 83b5a60cc0)