openimsdk/open-im-server · error
prometheus listen %d error %w
Error message
prometheus listen %d error %w
What it means
When Prometheus metrics are enabled, run() asks the kernel for a TCP listener on the configured port via net.Listen. If the OS refuses (port already bound, no permission, invalid port), the underlying error is wrapped as 'prometheus listen %d error %w'. The process cannot export metrics and startup fails.
Source
Thrown at cmd/main.go:289
go func() {
<-ctx.Done()
log.ZError(ctx, "context server exit cause", context.Cause(ctx))
}()
if prometheus := x.config.API.Prometheus; prometheus.Enable {
var (
port int
err error
)
if !prometheus.AutoSetPorts {
port, err = datautil.GetElemByIndex(prometheus.Ports, 0)
if err != nil {
return err
}
}
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
return fmt.Errorf("prometheus listen %d error %w", port, err)
}
defer listener.Close()
log.ZDebug(ctx, "prometheus start", "addr", listener.Addr())
go func() {
err := prommetrics.Start(listener)
if err == nil {
err = fmt.Errorf("http done")
}
cancel(fmt.Errorf("prometheus %w", err))
}()
}
go func() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)
select {
case <-ctx.Done():
returnView on GitHub (pinned to 175a7bb067)
Solutions
- Change the prometheus port in the component config to a free port and restart
- Find and stop the process occupying the port: lsof -i :PORT or ss -ltnp | grep PORT, then kill it
- If using a port <1024, run with CAP_NET_BIND_SERVICE or pick a high port
- Validate the configured port is 1-65535
Example fix
// before (config)
prometheus: { port: 9090 } # already in use
// after
prometheus: { port: 19090 } # free port Defensive patterns
Strategy: try-catch
Validate before calling
func portFree(p int) bool {
ln, err := net.Listen("tcp", fmt.Sprintf(":%d", p))
if err != nil { return false }
ln.Close()
return true
}
// call portFree(cfg.Prometheus.Port) before startup and pick another port if false Try / catch
if err := x.run(ctx); err != nil {
var perr *net.OpError
if errors.As(err, &perr) && strings.Contains(err.Error(), "prometheus listen") {
log.ZError(ctx, "prometheus port busy, pick a free port", err)
return
}
panic(err)
} Prevention
- Assign unique prometheus ports per component per host
- Pre-flight check port availability in deployment scripts
- Avoid privileged ports (<1024) for metrics
- Kill stale processes before restarts
When it happens
Trigger: Prometheus port in config is already used by another process (EADDRINUSE), the port is privileged (<1024) without root/CAP_NET_BIND_SERVICE, or the port value is invalid/out of range.
Common situations: Two OpenIM components on the same host configured with the same prometheus.port; a leftover zombie process holding the port; running in a container without permission to bind low ports; port 0 or >65535 in config.
Related errors
- config field %s %s not found
- no command to run
- standalone api port is 0
- invalid object enable: %s
- failed to get endpoints for service %s: %v
AI-assisted analysis of openimsdk/open-im-server@175a7bb067 (2026-09-04).
Data as JSON: /api/errors/bc13fb4e1d129945.
Report an issue: GitHub.