apache/pulsar · error · IllegalArgumentException
DeadLetter topic %s is invalid
Error message
DeadLetter topic %s is invalid
What it means
The dead-letter topic (used to store messages that exhaust max retries) is validated with TopicName.isValid in doCommonChecks; an invalid name causes function creation to fail with this IllegalArgumentException. A DLQ must be a real, addressable Pulsar topic for the retry policy to publish to it.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java:832
}
if (!isEmpty(functionConfig.getOutput())) {
if (!TopicName.isValid(functionConfig.getOutput())) {
throw new IllegalArgumentException(
String.format("Output topic %s is invalid", functionConfig.getOutput()));
}
}
if (!isEmpty(functionConfig.getLogTopic())) {
if (!TopicName.isValid(functionConfig.getLogTopic())) {
throw new IllegalArgumentException(
String.format("LogTopic topic %s is invalid", functionConfig.getLogTopic()));
}
}
if (!isEmpty(functionConfig.getDeadLetterTopic())) {
if (!TopicName.isValid(functionConfig.getDeadLetterTopic())) {
throw new IllegalArgumentException(
String.format("DeadLetter topic %s is invalid", functionConfig.getDeadLetterTopic()));
}
}
if (functionConfig.getParallelism() != null && functionConfig.getParallelism() <= 0) {
throw new IllegalArgumentException("Function parallelism must be a positive number");
}
// Ensure that topics aren't being used as both input and output
verifyNoTopicClash(allInputTopics, functionConfig.getOutput());
WindowConfig windowConfig = functionConfig.getWindowConfig();
if (windowConfig != null) {
// set auto ack to false since windowing framework is responsible
// for acking and not the function framework
@SuppressWarnings("deprecation")
Boolean windowAutoAck = functionConfig.getAutoAck();
if (windowAutoAck != null && windowAutoAck) {
throw new IllegalArgumentException("Cannot enable auto ack when using windowing functionality");View on GitHub (pinned to 820761864e)
Solutions
- Set a fully qualified DLQ name: persistent://public/default/my-dlq
- Also set maxMessageRetries >= 0 (a DLQ alone with infinite retries is rejected separately — see error 1419)
- Remove the deadLetterTopic if retries handling is not desired
- Validate with TopicName.isValid before submission
Example fix
// before
config.setDeadLetterTopic("dlq");
// after
config.setDeadLetterTopic("persistent://public/default/dlq");
config.setMaxMessageRetries(3); Defensive patterns
Strategy: validation
Validate before calling
String dlq = config.getDeadLetterTopic();
if (dlq != null && !dlq.isEmpty() && !TopicName.isValid(dlq.trim())) {
throw new IllegalArgumentException("Invalid DLQ topic: " + dlq);
}
if (dlq != null && !dlq.isEmpty()
&& (config.getMaxMessageRetries() == null || config.getMaxMessageRetries() < 0)) {
throw new IllegalArgumentException("DLQ requires maxMessageRetries >= 0");
} Type guard
boolean hasValidDlq(FunctionConfig c) {
String t = c.getDeadLetterTopic();
return t == null || t.isEmpty()
|| (TopicName.isValid(t.trim()) && c.getMaxMessageRetries() != null && c.getMaxMessageRetries() >= 0);
} Try / catch
try {
admin.functions().createFunction(functionConfig, sourceConfigLocation);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("DeadLetter")) {
// fix deadLetterTopic format and ensure maxMessageRetries is set
}
throw e;
} Prevention
- Always pair deadLetterTopic with a finite maxMessageRetries
- Create the DLQ topic ahead of deployment
- Use fully qualified DLQ names
- Keep DLQ naming conventions centralized in config templates
When it happens
Trigger: createFunction/updateFunction where functionConfig.getDeadLetterTopic() is non-empty and fails TopicName.isValid: bare topic name, malformed persistent:// URI, trailing whitespace, or empty segments.
Common situations: Setting --dead-letter-topic on the CLI with a short name, YAML placeholders not rendered, renaming tenant/namespace elsewhere and forgetting the DLQ field.
Related errors
- Invalid short topic name '%s', it should be in the format of
- Invalid topic name: %s
- Input topic %s is invalid
- Output topic %s is invalid
- LogTopic topic %s is invalid
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/6f4a0fec167a0178.
Report an issue: GitHub.