{"record":{"id":"bc13fb4e1d129945","repo":"openimsdk/open-im-server","slug":"prometheus-listen-d-error-w","errorCode":null,"errorMessage":"prometheus listen %d error %w","messagePattern":"prometheus listen (.+?) error %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/main.go","lineNumber":289,"sourceCode":"\tgo func() {\n\t\t<-ctx.Done()\n\t\tlog.ZError(ctx, \"context server exit cause\", context.Cause(ctx))\n\t}()\n\n\tif prometheus := x.config.API.Prometheus; prometheus.Enable {\n\t\tvar (\n\t\t\tport int\n\t\t\terr  error\n\t\t)\n\t\tif !prometheus.AutoSetPorts {\n\t\t\tport, err = datautil.GetElemByIndex(prometheus.Ports, 0)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tlistener, err := net.Listen(\"tcp\", fmt.Sprintf(\":%d\", port))\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"prometheus listen %d error %w\", port, err)\n\t\t}\n\t\tdefer listener.Close()\n\t\tlog.ZDebug(ctx, \"prometheus start\", \"addr\", listener.Addr())\n\t\tgo func() {\n\t\t\terr := prommetrics.Start(listener)\n\t\t\tif err == nil {\n\t\t\t\terr = fmt.Errorf(\"http done\")\n\t\t\t}\n\t\t\tcancel(fmt.Errorf(\"prometheus %w\", err))\n\t\t}()\n\t}\n\n\tgo func() {\n\t\tsigs := make(chan os.Signal, 1)\n\t\tsignal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/openimsdk/open-im-server/blob/175a7bb0673eca18e9d1b10bff4f728da6b1b513/cmd/main.go#L271-L307","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (config)\nprometheus: { port: 9090 }   # already in use\n// after\nprometheus: { port: 19090 }  # free port","handlingStrategy":"try-catch","validationCode":"func portFree(p int) bool {\n\tln, err := net.Listen(\"tcp\", fmt.Sprintf(\":%d\", p))\n\tif err != nil { return false }\n\tln.Close()\n\treturn true\n}\n// call portFree(cfg.Prometheus.Port) before startup and pick another port if false","typeGuard":null,"tryCatchPattern":"if err := x.run(ctx); err != nil {\n\tvar perr *net.OpError\n\tif errors.As(err, &perr) && strings.Contains(err.Error(), \"prometheus listen\") {\n\t\tlog.ZError(ctx, \"prometheus port busy, pick a free port\", err)\n\t\treturn\n\t}\n\tpanic(err)\n}","preventionTips":["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"],"tags":["network","prometheus","port-conflict","startup"],"backgroundTag":"port-already-in-use","analyzedSha":"175a7bb0673eca18e9d1b10bff4f728da6b1b513","analyzedAt":"2026-09-04T16:52:56.821Z","contentChangedAt":"2026-09-04T16:52:56.821Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}