apache/pulsar · warning · IOException

cause.getMessage()

Error message

cause.getMessage()

What it means

rethrowIOException normalizes a Throwable thrown while loading an additional servlet: IOException, RuntimeException, and Error are rethrown as-is; anything else is wrapped in a new IOException whose message is cause.getMessage(). Developers see this as an IOException during servlet (NAR) loading whose text is the underlying cause's message.

Source

Thrown at pulsar-broker-common/src/main/java/org/apache/pulsar/broker/web/plugin/servlet/AdditionalServletUtils.java:204

                }
            }
            default -> throw new IllegalArgumentException("Unsupported additional servlet type " + servletType);
        }
        throw new IllegalArgumentException("Additional servlet instance of type "
                + (servletInstance == null ? "null" : servletInstance.getClass().getName())
                + " doesn't implement the servlet interface required by the declared servlet type " + servletType);
    }

    private void rethrowIOException(Throwable cause)
            throws IOException {
        if (cause instanceof IOException) {
            throw (IOException) cause;
        } else if (cause instanceof RuntimeException) {
            throw (RuntimeException) cause;
        } else if (cause instanceof Error) {
            throw (Error) cause;
        } else {
            throw new IOException(cause.getMessage(), cause);
        }
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Inspect the IOException's message and its cause stack trace to find the underlying loading failure
  2. Rebuild/redeploy the servlet NAR — the cause is almost always in the plugin package
  3. Enable debug logging for the additional servlet loading path to capture the original throwable
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the NAR file exists and is readable before load
java.io.File nar = new java.io.File(narPath);
if (!nar.isFile() || !nar.canRead()) throw new java.io.FileNotFoundException(narPath);

Try / catch

try {
    servlet = AdditionalServletUtils.load(definition, narDir);
} catch (IOException e) {
    // message is cause.getMessage(); inspect cause chain for the real failure
    Throwable root = e; while (root.getCause() != null) root = root.getCause();
    log.error("Servlet load failed, root cause: {}", root.toString(), e);
}

Prevention

When it happens

Trigger: AdditionalServletUtils.load encounters a checked, non-IOException, non-RuntimeException, non-Error Throwable during servlet class loading/instantiation (e.g. a custom checked exception from plugin static initializers or class definition failures surfaced as a checked type).

Common situations: Corrupt or incompatible NAR files whose classloading throws unusual checked exceptions; plugin code throwing custom checked exceptions during initialization; unusual filesystem errors surfaced through non-standard exception types.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/447224070495a4a4. Report an issue: GitHub.