{"record":{"id":"59fcc564eb4dc05d","repo":"apache/pulsar","slug":"unsupported-additional-servlet-type-servlettype","errorCode":null,"errorMessage":"Unsupported additional servlet type ${servletType}","messagePattern":"Unsupported additional servlet type (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-broker-common/src/main/java/org/apache/pulsar/broker/web/plugin/servlet/AdditionalServletUtils.java","lineNumber":188,"sourceCode":"     * @return the servlet instance as a {@code jakarta.servlet.Servlet}\n     * @throws IllegalArgumentException if the servlet instance doesn't implement the servlet interface required\n     *         by the {@link AdditionalServlet#getServletType() servlet type} the additional servlet declares\n     */\n    public Servlet toJakartaServlet(AdditionalServlet additionalServlet) {\n        AdditionalServletType servletType = additionalServlet.getServletType();\n        Object servletInstance = additionalServlet.getServletInstance();\n        switch (servletType) {\n            case JAVAX_SERVLET -> {\n                if (servletInstance instanceof javax.servlet.Servlet javaxServlet) {\n                    return new ServletWrapper(javaxServlet);\n                }\n            }\n            case JAKARTA_SERVLET -> {\n                if (servletInstance instanceof Servlet jakartaServlet) {\n                    return jakartaServlet;\n                }\n            }\n            default -> throw new IllegalArgumentException(\"Unsupported additional servlet type \" + servletType);\n        }\n        throw new IllegalArgumentException(\"Additional servlet instance of type \"\n                + (servletInstance == null ? \"null\" : servletInstance.getClass().getName())\n                + \" doesn't implement the servlet interface required by the declared servlet type \" + servletType);\n    }\n\n    private void rethrowIOException(Throwable cause)\n            throws IOException {\n        if (cause instanceof IOException) {\n            throw (IOException) cause;\n        } else if (cause instanceof RuntimeException) {\n            throw (RuntimeException) cause;\n        } else if (cause instanceof Error) {\n            throw (Error) cause;\n        } else {\n            throw new IOException(cause.getMessage(), cause);\n        }\n    }","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/web/plugin/servlet/AdditionalServletUtils.java#L170-L206","documentation":"toJakartaServlet adapts an additional servlet's instance to jakarta.servlet.Servlet based on the servlet type the plugin declares. A switch over AdditionalServletType only knows JAVAX_SERVLET and JAKARTA_SERVLET; any other enum value reaches the default branch and throws this IllegalArgumentException. Today this mainly guards against null/unexpected values from a misimplemented or foreign plugin.","triggerScenarios":"A custom AdditionalServlet's getServletType() returns null (default branch hit via switch on null enum throws NPE) or a non-standard AdditionalServletType value added by a custom build; calling toJakartaServlet on a plugin whose enum constant is not one of the two supported types.","commonSituations":"Plugin written against a newer/older Pulsar API with an extra servlet type; a plugin incorrectly returning null from getServletType(); testing a hand-rolled AdditionalServlet implementation without setting servletType.","solutions":["Set the servlet type to JAVAX_SERVLET or JAKARTA_SERVLET in the plugin's getServletType() implementation and rebuild the NAR","Upgrade or fix the plugin so it declares one of the two supported AdditionalServletType values matching your Pulsar version","Ensure the servlet instance actually implements the interface matching the declared type (javax.servlet.Servlet vs jakarta.servlet.Servlet) to avoid the adjacent mismatch error"],"exampleFix":"// before\n@Override public AdditionalServletType getServletType() { return null; }\n// after\n@Override public AdditionalServletType getServletType() { return AdditionalServletType.JAKARTA_SERVLET; }","handlingStrategy":"type-guard","validationCode":"AdditionalServletType t = plugin.getServletType();\nif (t != AdditionalServletType.JAVAX_SERVLET && t != AdditionalServletType.JAKARTA_SERVLET)\n    throw new IllegalStateException(\"unsupported servlet type: \" + t);","typeGuard":"boolean hasSupportedServletType(AdditionalServlet p) {\n    return p.getServletType() == AdditionalServletType.JAVAX_SERVLET\n        || p.getServletType() == AdditionalServletType.JAKARTA_SERVLET;\n}","tryCatchPattern":"try {\n    Servlet s = AdditionalServletUtils.toJakartaServlet(plugin);\n} catch (IllegalArgumentException e) {\n    log.error(\"Cannot adapt servlet plugin: {}\", e.getMessage());\n}","preventionTips":["Return JAVAX_SERVLET or JAKARTA_SERVLET from getServletType(); never null","Match the servlet instance type to the declared type (javax vs jakarta Servlet)","Recompile plugins against the Pulsar version you deploy"],"tags":["plugin","servlet","type-mismatch","pulsar"],"backgroundTag":"unsupported-plugin-type","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}