apache/pulsar · error · NotSerializableException
A v5 authentication plugin (${v5Authentication.getClass().ge
Error message
A v5 authentication plugin (${v5Authentication.getClass().getName}) cannot be serialized with the client configuration. Configure authentication with authPluginClassName + authParams instead of a pre-built plugin instance when the configuration has to cross a boundary. What it means
ClientConfigurationData is Java-serializable, but a pre-built v5 Authentication plugin instance held in the v5Authentication field cannot safely cross a serialization boundary (it holds live state, threads, secrets). During writeObject, if a plugin instance is set and no authPluginClassName is configured, serialization aborts with NotSerializableException, telling you to express auth as class name + params instead.
Source
Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/conf/ClientConfigurationData.java:594
return operationTimeoutMs;
}
}
/**
* Refuse to serialize a configuration whose authentication would not survive the round trip.
*
* <p>A v5 authentication plugin is not {@link Serializable} and this slot is {@code transient}, so
* serializing would drop it silently and the deserialized configuration would authenticate as nobody —
* an authentication downgrade discovered as a broker rejection, far from its cause. The string form
* ({@code authPluginClassName} + {@code authParams}) does survive, and is what a remote or forked
* context should be configured with, so a configuration carrying one is allowed through.
*
* @param out the object output stream
* @throws IOException if the configuration cannot be written
*/
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
if (v5Authentication != null && StringUtils.isBlank(authPluginClassName)) {
throw new NotSerializableException("A v5 authentication plugin ("
+ v5Authentication.getClass().getName() + ") cannot be serialized with the client "
+ "configuration. Configure authentication with authPluginClassName + authParams instead "
+ "of a pre-built plugin instance when the configuration has to cross a boundary.");
}
out.defaultWriteObject();
}
public ClientConfigurationData clone() {
try {
return (ClientConfigurationData) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("Failed to clone ClientConfigurationData");
}
}
public InetSocketAddress getSocks5ProxyAddress() {
if (Objects.nonNull(socks5ProxyAddress)) {
return socks5ProxyAddress;View on GitHub (pinned to 820761864e)
Solutions
- Set authentication via authPluginClassName + authParams (the string form) before serializing, instead of a pre-built plugin instance.
- If you built the plugin programmatically, extract its class name and parameters and configure those on the copy you serialize.
- If you must keep the instance, exclude it from serialization (null it out on a copy) and re-instantiate it after deserialization.
Example fix
// before
conf.setAuthentication(myPluginInstance); // then serialize conf
// after
conf.setAuthPluginClassName("org.example.MyAuthPlugin");
conf.setAuthParams("param1=value1"); Defensive patterns
Strategy: validation
Validate before calling
if (conf.getAuthentication() != null /* v5 instance */
&& (conf.getAuthPluginClassName() == null || conf.getAuthPluginClassName().isBlank())) {
throw new IllegalStateException("set authPluginClassName + authParams before serializing config");
} Try / catch
try (java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(out)) {
oos.writeObject(conf);
} catch (java.io.NotSerializableException e) {
if (e.getMessage() != null && e.getMessage().startsWith("A v5 authentication plugin")) {
// rebuild conf with authPluginClassName + authParams and retry
} else throw e;
} Prevention
- Configure authentication by class name + params whenever the config may be serialized, cached, or sent across a process boundary.
- Keep pre-built plugin instances only in the live client, never in shared/serializable config objects.
- Serialize a copy with the plugin field nulled and re-attach the plugin after deserialization.
When it happens
Trigger: Serializing (java.io.ObjectOutputStream) a ClientConfigurationData whose v5Authentication field holds a plugin instance while authPluginClassName is blank — e.g. shipping the config object over the wire, caching it, or deep-copying via serialization.
Common situations: Frameworks or proxies that serialize client configs between processes; tests that serialize/deserialize configuration; storing configs in a serialized session state after programmatically setting a v5 plugin instance.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Invalid broker configuration. Authentication must be enabled
- No athenz domain name specified
- Invalid allowed offset for athenz role token verification sp
- Allowed offset for athenz role token verification must not b
- UNSUPPORTED_ISSUER
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/a7406e7d0e9a6f31.
Report an issue: GitHub.