apache/kafka · error · InvalidTopicException

Topic '${topic}' is invalid

Error message

Topic '${topic}' is invalid

What it means

Thrown as InvalidTopicException by TopicMetadataFetcher.getTopicMetadata when the broker's MetadataResponse carries Errors.INVALID_TOPIC_EXCEPTION for at least one requested topic. INVALID_TOPIC_EXCEPTION on the broker side means the topic name failed server-side validation (illegal characters, length, or '.' / '_' conflicts), distinct from UNKNOWN_TOPIC_OR_PARTITION which is silently skipped. The client surfaces it as a hard, non-retriable failure.

Source

Thrown at clients/src/main/java/org/apache/kafka/clients/consumer/internals/TopicMetadataFetcher.java:128

                Set<String> unauthorizedTopics = cluster.unauthorizedTopics();
                if (!unauthorizedTopics.isEmpty())
                    throw new TopicAuthorizationException(unauthorizedTopics);

                boolean shouldRetry = false;
                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)
                            shouldRetry = true;
                        else
                            throw new KafkaException("Unexpected error fetching metadata for topic " + topic,
                                    error.exception());
                    }
                }

                if (!shouldRetry) {
                    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

  1. Sanitize the topic name to match ^[a-zA-Z0-9\._-]{1,249}$ and avoid '.' or '..' exactly.
  2. If the topic was meant to exist, verify it via kafka-topics --describe; recreate with a valid name if it was auto-created with a bad name.
  3. Patch the producer of the bad topic name (config templating, env-var interpolation) so future runs don't recreate it.
  4. Disable auto.create.topics.enable on the broker if stray names are getting auto-created.

Example fix

// before
consumer.partitionsFor("orders/eur"); // '/' is illegal

// after
String topic = "orders.eur"; // legal charset
consumer.partitionsFor(topic);
Defensive patterns

Strategy: validation

Validate before calling

// Validate topic name against Kafka naming rules before subscribe/partitionFor.
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

import java.util.regex.Pattern;

/** Narrows a String to a Kafka-valid topic name (length 1-249, [A-Za-z0-9._-], not '.' / '..'). */
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.partitionsFor(topic);
} catch (org.apache.kafka.common.errors.InvalidTopicException e) {
    log.warn("Rejected invalid topic name '{}'; fix config/source, do not retry as-is", topic);
    throw e; // not retriable — the name will not become valid on its own
}

Prevention

When it happens

Trigger: Calling consumer.partitionsFor(topic) / listTopics() / subscribe() with a topic name containing illegal characters (must match [a-zA-Z0-9._-], max 249 chars), or a name equal to '.' or '..'. Also triggered when a topic name conflicts with an internal one.

Common situations: Topic names with forward slash '/', comma, or colon from templated config; names longer than 249 chars from dynamic naming; topic auto-created by another client with a typo (e.g. 'orders/eur'); using a fully-qualified 'namespace.topic' style where the namespace has illegal characters.

Related errors


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/b79ff38411bd7e47.json. Report an issue: GitHub.