{"record":{"id":"519a6d441e82d994","repo":"slackhq/nebula","slug":"already-listening-on-port-d","errorCode":null,"errorMessage":"already listening on port %d","messagePattern":"already listening on port (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"service/service.go","lineNumber":240,"sourceCode":"\t\treturn nil, errors.New(\"specific port required, got 0\")\n\t}\n\tif addr.Port < 0 || addr.Port >= math.MaxUint16 {\n\t\treturn nil, fmt.Errorf(\"invalid port %d\", addr.Port)\n\t}\n\tport := uint16(addr.Port)\n\n\tl := &tcpListener{\n\t\tport:   port,\n\t\ts:      s,\n\t\taddr:   addr,\n\t\taccept: make(chan net.Conn),\n\t}\n\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\n\tif _, ok := s.mu.listeners[port]; ok {\n\t\treturn nil, fmt.Errorf(\"already listening on port %d\", port)\n\t}\n\ts.mu.listeners[port] = l\n\n\treturn l, nil\n}\n\nfunc (s *Service) Wait() error {\n\treturn s.eg.Wait()\n}\n\nfunc (s *Service) Close() error {\n\ts.control.Stop()\n\treturn nil\n}\n\nfunc (s *Service) tcpHandler(r *tcp.ForwarderRequest) {\n\tendpointID := r.ID()\n","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/service/service.go#L222-L258","documentation":"Each Service keeps a registry of active listeners keyed by port under its mutex. Listen rejects a bind attempt when a listener already occupies the requested port, mirroring an EADDRINUSE from a real kernel. The port must be unique for the lifetime of the Service.","triggerScenarios":"Calling Service.Listen twice with the same wildcard port, e.g. Listen(\"tcp\", \":8080\") while a previous tcpListener on 8080 is still registered (service/service.go:240).","commonSituations":"Restarting a test server without closing the old listener; two test helpers both binding the same fixed port; forgetting to call Close() on the previous listener before rebinding; parallel tests sharing one Service.","solutions":["Close the existing listener (l.Close()) before listening on the same port again.","Use a different port for the new listener.","Create a new Service instance if you need an isolated port table."],"exampleFix":"// before\nl2, err := svc.Listen(\"tcp\", \":8080\") // already listening\n// after\nl1.Close()\nl2, err := svc.Listen(\"tcp\", \":8080\")","handlingStrategy":"try-catch","validationCode":"if activeListeners[port] {\n    return fmt.Errorf(\"port %d already bound by our own listener\", port)\n}","typeGuard":null,"tryCatchPattern":"l, err := svc.Listen(\"tcp\", fmt.Sprintf(\":%d\", port))\nif err != nil {\n    if strings.Contains(err.Error(), \"already listening on port\") {\n        // treat as EADDRINUSE: close stale listener or pick another port\n        return ErrPortInUse\n    }\n    return err\n}","preventionTips":["Always defer listener Close() in tests via t.Cleanup(func(){ l.Close() }).","Centralize listener creation so the same port can't be requested twice.","Prefer dynamic port selection per Service instance in parallel tests."],"tags":["network","gvisor","netstack","listen","port-in-use"],"backgroundTag":"address-already-in-use","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}