{"record":{"id":"efd0e43b1681ec95","repo":"slackhq/nebula","slug":"specific-port-required-got-0","errorCode":null,"errorMessage":"specific port required, got 0","messagePattern":"specific port required, got 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"service/service.go","lineNumber":222,"sourceCode":"func (s *Service) Dial(network, address string) (net.Conn, error) {\n\treturn s.DialContext(context.Background(), network, address)\n}\n\n// Listen listens on the provided address. Currently only TCP with wildcard\n// addresses are supported.\nfunc (s *Service) Listen(network, address string) (net.Listener, error) {\n\tif network != \"tcp\" && network != \"tcp4\" {\n\t\treturn nil, errors.New(\"only tcp is supported\")\n\t}\n\taddr, err := net.ResolveTCPAddr(network, address)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif addr.IP != nil && !bytes.Equal(addr.IP, []byte{0, 0, 0, 0}) {\n\t\treturn nil, fmt.Errorf(\"only wildcard address supported, got %q %v\", address, addr.IP)\n\t}\n\tif addr.Port == 0 {\n\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)","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/service/service.go#L204-L240","documentation":"Service.Listen requires the caller to pin an exact port; it resolves the address and rejects port 0 because the user-device listener cannot allocate an ephemeral port. The address must also be the IPv4 wildcard (0.0.0.0) with a specific nonzero port in the valid uint16 range.","triggerScenarios":"Calling s.Listen(\"tcp\", \"0.0.0.0:0\") (or any address where net.ResolveTCPAddr yields Port == 0) — commonly to let the OS pick a free port.","commonSituations":"Using :0 for ephemeral port allocation out of habit; omitting the port entirely in the address string (which resolves to 0); dynamically generated addresses with empty port fields.","solutions":["Choose an explicit port, e.g. \"0.0.0.0:4242\".","If a free port is needed, probe for one with net.Listen(\"tcp\", \"127.0.0.1:0\") on a normal listener, capture the chosen port, close it, and pass that port to s.Listen (accepting the small race).","Validate the port is 1–65535 before calling Listen."],"exampleFix":"// before\nln, err := s.Listen(\"tcp\", \"0.0.0.0:0\")\n// after\nln, err := s.Listen(\"tcp\", \"0.0.0.0:8080\")","handlingStrategy":"validation","validationCode":"addr, err := net.ResolveTCPAddr(\"tcp4\", address)\nif err != nil {\n    return err\n}\nif addr.Port == 0 {\n    return errors.New(\"Service.Listen requires an explicit non-zero port\")\n}","typeGuard":null,"tryCatchPattern":"ln, err := s.Listen(\"tcp\", address)\nif err != nil {\n    if err.Error() == \"specific port required, got 0\" {\n        return fmt.Errorf(\"pick an explicit port instead of :0 for %q\", address)\n    }\n    return err\n}","preventionTips":["Never use :0 with Service.Listen; pick a fixed port per service","If a free port is needed, reserve one with a temporary net.Listen on the loopback and reuse its port","Validate resolved port is in 1–65535 before calling Listen"],"tags":["service","tcp","port","nebula","validation"],"backgroundTag":"port-zero-not-allowed","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"}