provectus/kafka-ui · error · ValidationException

'filePath' property not set for custom serde

Error message

'filePath' property not set for custom serde ${serdeConfig.getName()}

What it means

Kafka UI's SerdesInitializer validates every custom serde config before loading it. A custom serde must specify both the fully-qualified 'className' of the Serde implementation and the 'filePath' of the JAR containing it; when filePath is null or empty the initializer refuses to proceed because the class cannot be located without its archive. It throws a ValidationException naming the offending serde.

Solutions

  1. Add the 'filePath' property pointing to the custom serde JAR to the serde config
  2. Verify the property name spelling (filePath) and that the value is non-empty in application.yaml or the API request payload
  3. If the JAR is bundled, set filePath to its classpath-relative or absolute path accessible to the kafka-ui process

Example fix

// before
serde:
  - name: my-serde
    className: com.example.MySerde
// after
serde:
  - name: my-serde
    className: com.example.MySerde
    filePath: /etc/kafka-ui/serde/my-serde.jar
Defensive patterns

Strategy: validation

Validate before calling

if (cfg == null || cfg.getClassName() == null || cfg.getClassName().isBlank() || cfg.getFilePath() == null || cfg.getFilePath().isBlank()) { throw new IllegalArgumentException("custom serde needs both className and filePath"); }

Type guard

boolean isValidCustomSerde(c) { return c != null && !isNullOrEmpty(c.getClassName()) && !isNullOrEmpty(c.getFilePath()); }

Try / catch

try { serde = initCustomSerde(cfg); } catch (ValidationException e) { log.error("bad serde config: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Calling createSerdeFromConfig / loadAndInitCustomSerde with a CustomSerde config whose filePath property is missing, empty, or set to null (e.g. only className was specified in serdeConfig).

Common situations: Hand-writing serde config in application.yaml/properties and forgetting the filePath key; copying a serde config snippet that only sets className; programmatically building a CustomSerde and leaving filePath unset.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at kafka-ui-api/src/main/java/com/provectus/kafka/ui/serdes/SerdesInitializer.java:263

        null
    );
  }

  @SneakyThrows
  private <T extends Serde> T createSerdeInstance(Class<T> clazz) {
    return clazz.getDeclaredConstructor().newInstance();
  }

  private SerdeInstance loadAndInitCustomSerde(SerdeConfig serdeConfig,
                                               PropertyResolver serdeProps,
                                               PropertyResolver clusterProps,
                                               PropertyResolver globalProps) {
    if (Strings.isNullOrEmpty(serdeConfig.getClassName())) {
      throw new ValidationException(
          "'className' property not set for custom serde " + serdeConfig.getName());
    }
    if (Strings.isNullOrEmpty(serdeConfig.getFilePath())) {
      throw new ValidationException(
          "'filePath' property not set for custom serde " + serdeConfig.getName());
    }
    var loaded = customSerdeLoader.loadAndConfigure(
        serdeConfig.getClassName(), serdeConfig.getFilePath(), serdeProps, clusterProps, globalProps);
    return new SerdeInstance(
        serdeConfig.getName(),
        loaded.getSerde(),
        nullablePattern(serdeConfig.getTopicKeysPattern()),
        nullablePattern(serdeConfig.getTopicValuesPattern()),
        loaded.getClassLoader()
    );
  }

  @Nullable
  private Pattern nullablePattern(@Nullable String pattern) {
    return pattern == null ? null : Pattern.compile(pattern);
  }
}

View on GitHub (pinned to 83b5a60cc0)