apache/pulsar · error · IOException
Failed to bind extension `${extensionName}` on ${address}
Error message
Failed to bind extension `${extensionName}` on ${address} What it means
ProxyService.startProxyExtension binds a Netty bootstrap for each configured proxy extension at its advertised address. If bind fails, the IOException names the extension and address so the operator knows which add-on listener is broken. Fail-fast behavior ensures extensions are not silently unavailable while the core proxy runs.
Source
Thrown at pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyService.java:457
bootstrap.childOption(ChannelOption.TCP_NODELAY, true);
bootstrap.childOption(ChannelOption.RCVBUF_ALLOCATOR,
new AdaptiveRecvByteBufAllocator(1024, 16 * 1024, 1 * 1024 * 1024));
EventLoopUtil.enableTriggeredMode(bootstrap);
DefaultThreadFactory defaultThreadFactory = new DefaultThreadFactory("pulsar-ext-" + extensionName);
EventLoopGroup dedicatedWorkerGroup =
EventLoopUtil.newEventLoopGroup(proxyConfig.getNumIOThreads(), false, defaultThreadFactory);
extensionsWorkerGroups.add(dedicatedWorkerGroup);
bootstrap.channel(EventLoopUtil.getServerSocketChannelClass(dedicatedWorkerGroup));
bootstrap.group(this.acceptorGroup, dedicatedWorkerGroup);
} else {
bootstrap = serverBootstrap.clone();
}
bootstrap.childHandler(initializer);
try {
bootstrap.bind(address).sync();
} catch (Exception e) {
throw new IOException("Failed to bind extension `" + extensionName + "` on " + address, e);
}
log.info()
.attr("extensionName", extensionName)
.attr("address", address)
.log("Successfully bound extension");
}
public BrokerDiscoveryProvider getDiscoveryProvider() {
return discoveryProvider;
}
public void close() throws IOException {
if (listenChannel != null) {
try {
listenChannel.close().sync();
} catch (InterruptedException e) {
log.info("Shutdown of listenChannel interrupted");
Thread.currentThread().interrupt();View on GitHub (pinned to 820761864e)
Solutions
- Check the extension's configured bind address/port and free the conflicting port (kill the stale process or pick a new port)
- Ensure no two proxy extensions or core proxy ports overlap in configuration
- Verify the bind address is a valid local interface and adjust if running in a container/VM
- Re-run the proxy after correcting the extension port config
Example fix
// before proxyExtensions=org.apache.pulsar.proxy.extension.socks5.Socks5ProxyService proxyExtensionPort0=1080 # occupied by a running SOCKS proxy // after proxyExtensionPort0=1081
Defensive patterns
Strategy: validation
Validate before calling
InetSocketAddress addr = resolveExtensionAddress(extensionName);
try (ServerSocket ss = new ServerSocket()) {
ss.bind(addr);
} catch (IOException e) {
throw new IllegalStateException("Extension " + extensionName + " port " + addr.getPort()
+ " unavailable: " + e.getMessage());
} Type guard
boolean extensionPortUnique(ProxyConfiguration cfg, int port) {
return port != cfg.getServicePort().orElse(-1)
&& port != cfg.getServicePortTls().orElse(-1)
&& port != cfg.getWebServicePort().orElse(-1);
} Try / catch
try {
proxyService.start();
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().contains("Failed to bind extension")) {
LOG.error("Proxy extension bind failed: {} (cause: {})", e.getMessage(), e.getCause());
}
throw e;
} Prevention
- Assign each proxy extension a distinct, non-overlapping port
- Check extension ports against core proxy/broker ports when planning deployments
- Kill stale processes from previous runs before starting extensions
- Verify the configured bind address exists on the host (especially in containers)
When it happens
Trigger: Calling ProxyService.start (which calls startProxyExtensions -> startProxyExtension) when an extension's configured bind address/port is already occupied, is a privileged port without permission, or the address does not exist on the host; the underlying bootstrap.bind(address).sync() throws and is wrapped in IOException.
Common situations: Two extensions configured with the same bind port; extension port colliding with a core proxy or broker port; leftover process from a previous test run holding the port; configuring a hostname that doesn't resolve to a local interface in a container.
Related errors
- Failed to bind Pulsar Proxy on port ${servicePort}
- Failed to start HTTP server on ports ${ports}
- Failed to load the extension for extension name `${extension
- Malformed extension found for extension name `${extensionNam
- extension for `${extensionName}` attempts to use ${address}
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/44adccb0efef19c7.
Report an issue: GitHub.