provectus/kafka-ui · error · ValidationException

Error writing to

Error message

Error writing to 

What it means

The final step of writeYamlToFile() wraps Files.writeString in try/catch; any IOException while actually writing the YAML (disk full, I/O error, filesystem failure) is rethrown as ValidationException with message 'Error writing to <path>' and the original IOException as cause.

Solutions

  1. Inspect the cause (IOException) in the logs for the concrete reason (NoSpaceLeftOnDevice, etc.)
  2. Free disk space or expand the volume, then retry the config change
  3. Re-mount/repair the volume and confirm the path is writable before retrying

Example fix

// shell: diagnose
 df -h /etc/kafka-ui   # check free space
 lsattr application-config.yml  # check immutable flag
// after
 chattr -i application-config.yml  # if immutable flag was set
Defensive patterns

Strategy: try-catch

Try / catch

try {
  dynamicConfigOperations.persist(props);
} catch (ValidationException e) {
  log.error("Failed writing dynamic config: {}", e.getMessage(), e.getCause());
  Throwable cause = e.getCause();
  if (cause instanceof IOException io && io.getMessage().contains("No space left")) {
    // alert on disk usage and retry after freeing space
  }
}

Prevention

When it happens

Trigger: Persisting dynamic config when the underlying Files.writeString fails: no space left on device, I/O error on the volume, transient NFS failure, or the file becoming unwritable between the earlier check and the write.

Common situations: Full disk on the node hosting the config volume; volume detached or remounted read-only after startup; quota exceeded on the storage.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of provectus/kafka-ui@83b5a60cc0 (2026-09-08). Data as JSON: /api/errors/b9a3c8feb1b2deea. Report an issue: GitHub.

Appendix: source

Thrown at kafka-ui-api/src/main/java/com/provectus/kafka/ui/util/DynamicConfigOperations.java:191

    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()) {
      @Override
      protected NodeTuple representJavaBeanProperty(Object javaBean,
                                                    Property property,
                                                    Object propertyValue,
                                                    Tag customTag) {
        if (propertyValue == null) {
          return null; // if value of property is null, ignore it.
        } else {
          return super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
        }
      }
    };

View on GitHub (pinned to 83b5a60cc0)