apache/pulsar · error · IOException
Additional servlets `${name}` does NOT provide an additional
Error message
Additional servlets `${name}` does NOT provide an additional servlets implementation What it means
When the broker loads an additional servlet NAR package (via AdditionalServletUtils.load), it reads `META-INF/services/additional_servlet.yml` from the archive. That definition must specify an `additionalServletClass`. If the class field is blank/missing, load() throws this IOException because there is no implementation class to instantiate.
Source
Thrown at pulsar-broker-common/src/main/java/org/apache/pulsar/broker/web/plugin/servlet/AdditionalServletUtils.java:140
/**
* Load the additional servlets according to the additional servlet definition.
*
* @param metadata the additional servlet definition.
*/
@SuppressWarnings("unchecked")
public AdditionalServletWithClassLoader load(
AdditionalServletMetadata metadata, String narExtractionDirectory) throws IOException {
final File narFile = metadata.getArchivePath().toAbsolutePath().normalize().toFile();
NarClassLoader ncl = NarClassLoaderBuilder.builder()
.narFile(narFile)
.parentClassLoader(AdditionalServlet.class.getClassLoader())
.extractionDirectory(narExtractionDirectory)
.build();
AdditionalServletDefinition def = getAdditionalServletDefinition(ncl);
if (StringUtils.isBlank(def.getAdditionalServletClass())) {
throw new IOException("Additional servlets `" + def.getName() + "` does NOT provide an "
+ "additional servlets implementation");
}
try {
Class additionalServletClass = ncl.loadClass(def.getAdditionalServletClass());
Object additionalServlet = additionalServletClass.getDeclaredConstructor().newInstance();
if (!(additionalServlet instanceof AdditionalServlet)) {
throw new IOException("Class " + def.getAdditionalServletClass()
+ " does not implement additional servlet interface");
}
AdditionalServlet servlet = (AdditionalServlet) additionalServlet;
return new AdditionalServletWithClassLoader(servlet, ncl);
} catch (Throwable t) {
rethrowIOException(t);
return null;
}
}
View on GitHub (pinned to 820761864e)
Solutions
- Add/fix `additionalServletClass: <fully.qualified.ClassName>` in the NAR's META-INF/services/additional_servlet.yml and rebuild the NAR
- Verify with `unzip -p your.nar META-INF/services/additional_servlet.yml` that the field is present and non-blank
- Replace the NAR with an official/release-built servlet NAR to rule out a corrupted archive
Example fix
# before (additional_servlet.yml) name: my-servlet description: my servlet # after name: my-servlet description: my servlet additionalServletClass: com.example.MyAdditionalServlet
Defensive patterns
Strategy: validation
Validate before calling
try (JarFile nar = new JarFile(narPath)) {
String yml = nar.getInputStream(nar.getEntry("META-INF/services/additional_servlet.yml"))
.readAllBytes() != null ? new String(nar.getInputStream(
nar.getEntry("META-INF/services/additional_servlet.yml")).readAllBytes()) : null;
if (yml == null || !yml.contains("additionalServletClass:"))
throw new IllegalStateException("NAR descriptor missing additionalServletClass");
} Try / catch
try {
servlet = AdditionalServletUtils.load(metadata, narExtractionDir);
} catch (IOException e) {
log.error("Failed to load servlet NAR {}: {}", metadata.getArchivePath(), e.getMessage());
} Prevention
- Always set additionalServletClass in additional_servlet.yml
- Inspect the NAR descriptor (unzip -p) before deploying
- Build NARs with the official Pulsar plugin archetype/template
When it happens
Trigger: Deploying a .nar whose additional_servlet.yml lacks the `additionalServletClass` key or has it empty; a hand-built NAR packaged with a minimal/incorrect descriptor; a renamed or re-packaged servlet jar losing the metadata file.
Common situations: Building a custom servlet NAR and forgetting the descriptor field; using a NAR generated for a different plugin type (e.g. an entrypoint/function NAR) whose yml schema differs; upstream packaging regression after a Pulsar version change.
Related errors
- Class ${className} does not implement additional servlet int
- Unsupported additional servlet type ${servletType}
- Additional servlet instance of type ${className} doesn't imp
- No additional servlet is found for name `${servletName}`. Av
- Failed to load the additional servlet for name `${servletNam
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/754d9c4dd1334f28.
Report an issue: GitHub.