apache/kafka · error · InvalidTopicException
Topic '${topic}' is invalid
Error message
Topic '${topic}' is invalid What it means
Async-consumer counterpart of error 233. Thrown as InvalidTopicException by TopicMetadataRequestManager.handleTopicMetadataResponse when the MetadataResponse errors map contains Errors.INVALID_TOPIC_EXCEPTION for a topic. The new consumer network thread surfaces a server-side topic-name validation failure as a hard, non-retriable exception, propagated through the inflightRequests CompletableFuture.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/internals/TopicMetadataRequestManager.java:260
Cluster cluster = response.buildCluster();
final Set<String> unauthorizedTopics = cluster.unauthorizedTopics();
if (!unauthorizedTopics.isEmpty())
throw new TopicAuthorizationException(unauthorizedTopics);
Map<String, Errors> errors = response.errors();
if (!errors.isEmpty()) {
// if there were errors, we need to check whether they were fatal or whether
// we should just retry
log.debug("Topic metadata fetch included errors: {}", errors);
for (Map.Entry<String, Errors> errorEntry : errors.entrySet()) {
String topic = errorEntry.getKey();
Errors error = errorEntry.getValue();
if (error == Errors.INVALID_TOPIC_EXCEPTION)
throw new InvalidTopicException("Topic '" + topic + "' is invalid");
else if (error == Errors.UNKNOWN_TOPIC_OR_PARTITION)
// if a requested topic is unknown, we just continue and let it be absent
// in the returned map
continue;
else if (error.exception() instanceof RetriableException)
throw error.exception();
else
throw new KafkaException("Unexpected error fetching metadata for topic " + topic,
error.exception());
}
}
HashMap<String, List<PartitionInfo>> topicsPartitionInfos = new HashMap<>();
for (String topic : cluster.topics())
topicsPartitionInfos.put(topic, cluster.partitionsForTopic(topic));
return topicsPartitionInfos;
}
View on GitHub (pinned to c31c9215e1)
Solutions
- Sanitize the topic name to ^[a-zA-Z0-9\._-]{1,249}$ and avoid the literals '.' and '..'.
- Verify the topic actually exists with kafka-topics --describe; if a stray invalid topic was auto-created, delete and recreate with a valid name.
- Disable auto.create.topics.enable on the broker to prevent silent creation of bad names.
- Patch whatever templating/interpolation produced the bad name so future runs are clean.
Example fix
// before
String topic = env.get("TOPIC"); // "orders/eur" -> illegal
consumer.partitionsFor(topic);
// after
String raw = env.get("TOPIC");
String topic = raw.replaceAll("[^a-zA-Z0-9._-]", "_");
consumer.partitionsFor(topic); Defensive patterns
Strategy: validation
Validate before calling
// Validate topic name up front (same rule Kafka enforces server-side).
static final java.util.regex.Pattern NAME = java.util.regex.Pattern.compile("^[a-zA-Z0-9._-]+$");
static boolean isValidTopicName(String t) {
return t != null && t.length() >= 1 && t.length() <= 249
&& !t.equals(".") && !t.equals("..")
&& NAME.matcher(t).matches();
}
if (!isValidTopicName(topic)) throw new IllegalArgumentException("bad topic name: " + topic); Type guard
/** Narrows a String to a Kafka-valid topic name. */
static boolean isValidTopicName(String topic) {
if (topic == null || topic.isEmpty() || topic.length() > 249) return false;
if (topic.equals(".") || topic.equals("..")) return false;
for (int i = 0; i < topic.length(); i++) {
char c = topic.charAt(i);
boolean ok = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9') || c == '.' || c == '_' || c == '-';
if (!ok) return false;
}
return true;
} Try / catch
try {
consumer.subscribe(java.util.Set.of(topic));
} catch (org.apache.kafka.common.errors.InvalidTopicException e) {
log.warn("Rejected invalid topic name '{}'; correct source/config", topic);
throw e; // name will not self-correct — do not retry unchanged
} Prevention
- Validate topic names at the configuration boundary before they reach the client.
- Centralize topic-name construction behind a factory that enforces length and charset.
- Reject '.', '..', and any path-like or control characters explicitly.
- Add a config-load test that fails the deploy if any topic name violates the rule.
When it happens
Trigger: Calling any metadata-triggering operation (partitionsFor, listTopics, subscribe) with a topic name that fails broker-side validation (illegal characters, length > 249, or '.' / '..' literal). The new consumer surfaces the same INVALID_TOPIC_EXCEPTION code as the legacy path.
Common situations: Templated or env-var-derived topic names containing '/', ':', or spaces; topic name auto-created by another producer with a typo; dynamic naming producing > 249 chars; mixed environments where one cluster tolerates a name another rejects.
Related errors
- Topic '${topic}' is invalid
- Not authorized to access topics: ${unauthorizedTopics}
- Unexpected error fetching metadata for topic ${topic}
- The target time for partition {} is {}. The target time cann
- The timeout cannot be negative.
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/035e40a06ec60466.json.
Report an issue: GitHub.