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

  1. Sanitize the topic name to ^[a-zA-Z0-9\._-]{1,249}$ and avoid the literals '.' and '..'.
  2. Verify the topic actually exists with kafka-topics --describe; if a stray invalid topic was auto-created, delete and recreate with a valid name.
  3. Disable auto.create.topics.enable on the broker to prevent silent creation of bad names.
  4. 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

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


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