apache/pulsar · error · RuntimeException
Invalid message config key '
Error message
Invalid message config key '
What it means
TypedMessageBuilderImpl.loadConf(Map) applies known message config keys via a switch; any key not matching a CONF_* constant hits the default branch and throws RuntimeException("Invalid message config key '" + key + "'"). loadConf only supports a fixed set of message property names, so a typo or an unsupported key is a hard error.
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/TypedMessageBuilderImpl.java:270
this.sequenceId(checkType(value, Long.class));
break;
case CONF_REPLICATION_CLUSTERS:
this.replicationClusters(checkType(value, List.class));
break;
case CONF_DISABLE_REPLICATION:
boolean disableReplication = checkType(value, Boolean.class);
if (disableReplication) {
this.disableReplication();
}
break;
case CONF_DELIVERY_AFTER_SECONDS:
this.deliverAfter(checkType(value, Long.class), TimeUnit.SECONDS);
break;
case CONF_DELIVERY_AT:
this.deliverAt(checkType(value, Long.class));
break;
default:
throw new RuntimeException("Invalid message config key '" + key + "'");
}
});
return this;
}
public MessageMetadata getMetadataBuilder() {
return msgMetadata;
}
public Message<T> getMessage() {
beforeSend();
return MessageImpl.create(msgMetadata, content, schema, getTopic());
}
public long getPublishTime() {
return msgMetadata.getPublishTime();
}
View on GitHub (pinned to 820761864e)
Solutions
- Fix the key name to one of the supported TypedMessageBuilder config keys (e.g. 'deliverAt', 'deliverAfter', 'eventTime', 'sequenceId', 'properties').
- Replace loadConf with direct builder calls (typedMessageBuilder.deliverAt(...), .properties(...)) so the compiler catches mistakes.
- Validate incoming conf map keys against the supported whitelist before calling loadConf.
Example fix
// before
builder.loadConf(Map.of("deliverAtTime", System.currentTimeMillis() + 5000));
// after
builder.loadConf(Map.of("deliverAt", System.currentTimeMillis() + 5000)); Defensive patterns
Strategy: validation
Validate before calling
Set<String> ALLOWED = Set.of("key", "properties", "eventTime", "sequenceId",
"replicationClusters", "disableReplication", "deliverAt", "deliverAfter", "value");
conf.keySet().forEach(k -> {
if (!ALLOWED.contains(k)) throw new IllegalArgumentException("Unsupported message config key: " + k);
}); Try / catch
try {
builder.loadConf(conf);
} catch (RuntimeException e) {
if (e.getMessage().startsWith("Invalid message config key")) {
log.error("bad message conf key: {}", e.getMessage());
} else throw e;
} Prevention
- Prefer direct TypedMessageBuilder setter methods over loadConf so typos fail at compile time.
- Keep a whitelist constant of supported message config keys and validate maps against it.
- Check key names against the producer's CONF_* constants when copy-pasting configs.
When it happens
Trigger: Passing a Map to TypedMessageBuilder.loadConf() containing any key not in the supported set (key, properties, eventTime, sequenceId, replicationClusters, disableReplication, deliverAt, deliverAfter, value, etc.), e.g. a misspelled 'deliverAtTime' instead of 'deliverAt'.
Common situations: Reusing producer-level config keys in message conf; typos after refactoring from deprecated keys; building conf maps from external config files where keys are not validated; copy-pasting keys between loadConf on Producer and on TypedMessageBuilder which accept different key sets.
Related errors
- The shared resource doesn't support thread pool configurati
- No resources have been configured while using shareConfigure
- AutoScaledReceiverQueueSize is not supported in ZeroQueueCon
- certFilePath must not be null
- keyFilePath must not be null
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/bf2266ac3dc1e266.
Report an issue: GitHub.