{"record":{"id":"03fa54606659c56d","repo":"openimsdk/open-im-server","slug":"rpcports-index-out-of-range-s-w","errorCode":null,"errorMessage":"rpcPorts index out of range %s %w","messagePattern":"rpcPorts index out of range (.+?) %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/common/startrpc/start.go","lineNumber":222,"sourceCode":"\t}\n\n\tvar (\n\t\trpcServer       *grpc.Server\n\t\trpcGracefulStop chan struct{}\n\t)\n\n\tonGrpcServiceRegistrar := func(desc *grpc.ServiceDesc, impl any) {\n\t\tif rpcServer != nil {\n\t\t\trpcServer.RegisterService(desc, impl)\n\t\t\treturn\n\t\t}\n\t\tvar rpcListenAddr string\n\t\tif autoSetPorts {\n\t\t\trpcListenAddr = net.JoinHostPort(listenIP, \"0\")\n\t\t} else {\n\t\t\trpcPort, err := datautil.GetElemByIndex(rpcPorts, index)\n\t\t\tif err != nil {\n\t\t\t\tcancel(fmt.Errorf(\"rpcPorts index out of range %s %w\", rpcRegisterName, err))\n\t\t\t\treturn\n\t\t\t}\n\t\t\trpcListenAddr = net.JoinHostPort(listenIP, strconv.Itoa(rpcPort))\n\t\t}\n\t\trpcListener, err := net.Listen(\"tcp\", rpcListenAddr)\n\t\tif err != nil {\n\t\t\tcancel(fmt.Errorf(\"listen rpc %s %s %w\", rpcRegisterName, rpcListenAddr, err))\n\t\t\treturn\n\t\t}\n\n\t\trpcServer = grpc.NewServer(options...)\n\t\trpcServer.RegisterService(desc, impl)\n\t\trpcGracefulStop = make(chan struct{})\n\t\trpcPort := rpcListener.Addr().(*net.TCPAddr).Port\n\t\tlog.ZDebug(ctx, \"rpc start register\", \"rpcRegisterName\", rpcRegisterName, \"registerIP\", registerIP, \"rpcPort\", rpcPort)\n\t\tgrpcOpt := grpc.WithTransportCredentials(insecure.NewCredentials())\n\t\trpcGracefulStop = make(chan struct{})\n\t\tgo func() {","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/openimsdk/open-im-server/blob/175a7bb0673eca18e9d1b10bff4f728da6b1b513/pkg/common/startrpc/start.go#L204-L240","documentation":"During RPC server startup, when autoSetPorts is disabled, the service picks its port from the rpcPorts list by its index. datautil.GetElemByIndex returns an error when index exceeds the list length, and startup is cancelled with 'rpcPorts index out of range'. It means the configured rpcPorts array is shorter than the number of RPC services being started.","triggerScenarios":"Calling startrpc.Start with autoSetPorts=false and an rpcPorts config slice shorter than the number of RPC services being registered (index >= len(rpcPorts)).","commonSituations":"Config file omits or truncates the rpcPorts list while multiple RPC services are launched; a new RPC service was added to the binary but the ops-supplied rpcPorts array was not extended; mismatched config versions between nodes.","solutions":["Add enough entries to the rpcPorts config so every indexed RPC service has a port","Set autoSetPorts=true (or the equivalent config flag) to let each service bind to an ephemeral port","Verify the number of RPC services started matches the number of configured ports"],"exampleFix":"// before (config)\nrpcPorts: [10110]\n// after (two RPC services)\nrpcPorts: [10110, 10111]","handlingStrategy":"validation","validationCode":"if !autoSetPorts && len(rpcPorts) <= index {\n    return fmt.Errorf(\"rpcPorts must contain at least %d entries, got %d\", index+1, len(rpcPorts))\n}","typeGuard":null,"tryCatchPattern":"if err := startrpc.Start(ctx, cfg); err != nil {\n    if strings.Contains(err.Error(), \"rpcPorts index out of range\") {\n        // fix config and retry or exit with clear message\n    }\n    return err\n}","preventionTips":["Keep rpcPorts length >= number of RPC services started per binary","Validate config arrays at boot before binding listeners","Prefer autoSetPorts in dynamic environments (K8s)","Add a config lint test covering all service binaries"],"tags":["config","startup","grpc","ports"],"backgroundTag":"rpc-port-config-missing","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"}