provectus/kafka-ui · error · ValidationException

className can't be set for built-in serde

Error message

className can't be set for built-in serde

What it means

Serde names that match built-in serde types (e.g. protobuf, avro-schema-registry) are instantiated from internal classes; supplying a className would conflict with the built-in class resolution, so createSerdeWithBuiltInSerdeName throws ValidationException.

Solutions

  1. Remove the className field from the entry using the built-in serde name
  2. Or rename the serde to a non-built-in name if you actually want a custom class

Example fix

// before
serde:
  - name: protobuf
    className: com.provectus.kafka.ui.serdes.builtin.ProtobufSerde
// after
serde:
  - name: protobuf
Defensive patterns

Strategy: validation

Validate before calling

if (isBuiltInSerdeName(cfg.getName()) && cfg.getClassName() != null)
  throw new IllegalArgumentException("className not allowed for built-in serde " + cfg.getName());

Try / catch

try {
  serde = createSerdeFromConfig(cfg, ...);
} catch (ValidationException e) {
  log.error("Bad serde config for {}: {}", cfg.getName(), e.getMessage());
  throw e;
}

Prevention

When it happens

Trigger: Using a built-in serde name in config while also setting className on the same serde entry.

Common situations: User copies a custom-serde config template and edits only filePath, leaving className set while keeping a built-in name like 'protobuf'.

Related errors


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

Appendix: source

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

      var builtInSerdeClass = builtInSerdeClasses.values().stream()
          .filter(c -> c.getName().equals(serdeConfig.getClassName()))
          .findAny();
      // built-in serde type with custom name
      if (builtInSerdeClass.isPresent()) {
        return createSerdeWithBuiltInClass(builtInSerdeClass.get(), serdeConfig, serdeProps, clusterProps, globalProps);
      }
    }
    log.info("Loading custom serde {}", serdeConfig.getName());
    return loadAndInitCustomSerde(serdeConfig, serdeProps, clusterProps, globalProps);
  }

  private SerdeInstance createSerdeWithBuiltInSerdeName(SerdeConfig serdeConfig,
                                                        PropertyResolver serdeProps,
                                                        PropertyResolver clusterProps,
                                                        PropertyResolver globalProps) {
    String name = serdeConfig.getName();
    if (serdeConfig.getClassName() != null) {
      throw new ValidationException("className can't be set for built-in serde");
    }
    if (serdeConfig.getFilePath() != null) {
      throw new ValidationException("filePath can't be set for built-in serde types");
    }
    var clazz = builtInSerdeClasses.get(name);
    BuiltInSerde serde = createSerdeInstance(clazz);
    if (serdeConfig.getProperties() == null || serdeConfig.getProperties().isEmpty()) {
      if (!autoConfigureSerde(serde, clusterProps, globalProps)) {
        // no properties provided and serde does not support auto-configuration
        throw new ValidationException(name + " serde is not configured");
      }
    } else {
      // configuring serde with explicitly set properties
      serde.configure(serdeProps, clusterProps, globalProps);
    }
    return new SerdeInstance(
        name,
        serde,

View on GitHub (pinned to 83b5a60cc0)