provectus/kafka-ui · error · ValidationException
Serde ' ' can't be applied to ' ' topic
Error message
Serde '%s' can't be applied to '%s' topic %s
What it means
getSerdeForDeserialize validates the explicitly requested serdeName against the topic and type (key or value) via canDeserialize. If the serde exists but cannot deserialize that side of that topic, this ValidationException is thrown; when no name is given, kafka-ui auto-suggests a suitable serde instead.
Solutions
- Omit the keySerde/valueSerde parameter so kafka-ui auto-suggests a suitable serde for the topic
- Pick a serde that supports that topic side, e.g. String for non-registry-encoded keys
- If using SR-based serdes, confirm the subject/mapping for this topic (and key vs value) exists in Schema Registry
- Re-check the request: ensure a value-side serde wasn't passed as keySerde or vice versa
Example fix
// before GET /api/clusters/c1/topics/t/messages?valueSerde=Avro // Avro can't deserialize this topic's values // after GET /api/clusters/c1/topics/t/messages // let kafka-ui suggest the serde // or pick a compatible serde explicitly GET /api/clusters/c1/topics/t/messages?valueSerde=String
Defensive patterns
Strategy: validation
Validate before calling
var serdes = deserializationService.getSerdesFor(cluster);
boolean usable = serdes.serdeForName(serdeName)
.map(s -> s.canDeserialize(topic, type))
.orElse(false);
if (!usable) serdeName = null; // let kafka-ui suggest one Try / catch
try {
messages = kafkaUiApi.getMessages(topic, keySerde, valueSerde);
} catch (ValidationException e) {
if (e.getMessage().contains("can't be applied")) {
messages = kafkaUiApi.getMessages(topic, null, null); // auto-suggest serdes
}
} Prevention
- Prefer omitting keySerde/valueSerde and let kafka-ui suggest serdes per topic
- Refresh saved consumption queries after topic/schema config changes
- Verify key vs value serde parameters aren't swapped in API calls
When it happens
Trigger: Requesting message consumption/preview with an explicit keySerde or valueSerde query parameter whose canDeserialize(topic, type) is false - e.g. asking an Avro Schema Registry serde to deserialize the key of a topic whose key subject/mapping doesn't exist, or using a serde that only supports VALUE.
Common situations: Saved UI links/queries carrying a serde name from a different topic; topic renamed or schema subject mappings changed after the query was bookmarked; swapping keySerde and valueSerde parameters in an API call; cluster migration where the new cluster lacks the subject for that topic.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Serde can't be applied for ' ' topic's serialization
- Application config isn't valid. Cluster names should be…
- Application config isn't valid. Two clusters can't have the…
- Schema Registry is not set for cluster
- 'filePath' property not set for custom serde
AI-assisted analysis of provectus/kafka-ui@83b5a60cc0 (2026-09-08).
Data as JSON: /api/errors/c775418ad61cc5a3.
Report an issue: GitHub.
Appendix: source
Thrown at kafka-ui-api/src/main/java/com/provectus/kafka/ui/service/DeserializationService.java:72
.orElseThrow(() -> new ValidationException(
String.format("Serde %s not found", serdeName)));
if (!serde.canSerialize(topic, type)) {
throw new ValidationException(
String.format("Serde %s can't be applied for '%s' topic's %s serialization", serde, topic, type));
}
return serde.serializer(topic, type);
}
private SerdeInstance getSerdeForDeserialize(KafkaCluster cluster,
String topic,
Serde.Target type,
@Nullable String serdeName) {
var serdes = getSerdesFor(cluster);
if (serdeName != null) {
var serde = serdes.serdeForName(serdeName)
.orElseThrow(() -> new ValidationException(String.format("Serde '%s' not found", serdeName)));
if (!serde.canDeserialize(topic, type)) {
throw new ValidationException(
String.format("Serde '%s' can't be applied to '%s' topic %s", serdeName, topic, type));
}
return serde;
} else {
return serdes.suggestSerdeForDeserialize(topic, type);
}
}
public ProducerRecordCreator producerRecordCreator(KafkaCluster cluster,
String topic,
String keySerdeName,
String valueSerdeName) {
return new ProducerRecordCreator(
getSerializer(cluster, topic, Serde.Target.KEY, keySerdeName),
getSerializer(cluster, topic, Serde.Target.VALUE, valueSerdeName)
);
}
View on GitHub (pinned to 83b5a60cc0)