{"record":{"id":"f47a689b7f2fcc7c","repo":"gastownhall/beads","slug":"listen-on-s-w","errorCode":null,"errorMessage":"listen on %s: %w","messagePattern":"listen on (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dbproxy/proxy/server.go","lineNumber":227,"sourceCode":"\tdefer stopEpochWatch()\n\n\t// abortInterruptedStart tears down a doomed start whose stop epoch\n\t// advanced mid-boot. The interrupting stop is polling proxy.lock under a\n\t// budget (shutdownConfirmDeadline) far smaller than a backend stop can\n\t// take, and nothing has been published, so release the lock BEFORE the\n\t// backend teardown instead of starving the stopper into its timeout.\n\tabortInterruptedStart := func() error {\n\t\tp.stats.IncBackendStop()\n\t\treleaseLock()\n\t\t_ = stopBackendBounded(p.server)\n\t\treturn fmt.Errorf(\"%w for %s: stop epoch advanced during startup\", errStartInterrupted, p.rootDir)\n\t}\n\n\taddr := fmt.Sprintf(\"127.0.0.1:%d\", p.port)\n\n\tln, err := net.Listen(\"tcp\", addr)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"listen on %s: %w\", addr, err)\n\t}\n\n\tp.listener = ln\n\tdefer func() { _ = ln.Close() }()\n\tp.stats.IncListenAndServe()\n\tdataPort, ok := ln.Addr().(*net.TCPAddr)\n\tif !ok {\n\t\treturn fmt.Errorf(\"proxy: unexpected data listener address %T\", ln.Addr())\n\t}\n\n\tif _, err := identity.WriteSecret(p.rootDir); err != nil {\n\t\treturn fmt.Errorf(\"write proxy secret: %w\", err)\n\t}\n\n\tvar identMu sync.RWMutex\n\tidentReply := identity.IdentReply{\n\t\tSchema:   pidfile.SchemaV2,\n\t\tRole:     pidfile.KindProxy,","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dbproxy/proxy/server.go#L209-L245","documentation":"This error wraps the failure of net.Listen(\"tcp\", \"127.0.0.1:<port>\") when the dbproxy tries to open its data listener during ListenAndServe. The library throws it whenever the OS refuses to bind the chosen loopback TCP port, and the underlying OS error is preserved via %w so callers can inspect it with errors.Is.","triggerScenarios":"ListenAndServe is called and net.Listen on the proxy's configured port fails - typically because the port is already bound by another process, the port is 0-but-restricted, or the loopback interface is unavailable.","commonSituations":"A stale proxy process still holds the port (orphaned after a crash); two proxies configured with the same port; running in a sandbox/container without loopback networking; port falls in a blocked ephemeral range; SELinux/AppArmor denying bind.","solutions":["Check what holds the port with `lsof -i :<port>` or `ss -ltnp` and kill the stale proxy process","Reconfigure p.port to a free port, or confirm the ephemeral/dynamic port selection is enabled","Verify loopback networking is available (container/netns restrictions)","Check firewall/SELinux logs if bind is denied by policy"],"exampleFix":"// before\np := proxy.New(proxy.WithPort(8080)) // fixed port, already in use\n// after\np := proxy.New(proxy.WithPort(0)) // let the OS pick a free loopback port","handlingStrategy":"validation","validationCode":"// Before starting, check the port is bindable\nln, err := net.Listen(\"tcp\", \"127.0.0.1:0\")\nif err != nil { log.Fatalf(\"no loopback networking: %v\", err) }\n_ = ln.Close()\n// or verify the specific port is free:\nif c, err := net.DialTimeout(\"tcp\", \"127.0.0.1:8080\", time.Second); err == nil { c.Close(); log.Fatal(\"port 8080 in use\") }","typeGuard":null,"tryCatchPattern":"err := p.ListenAndServe(ctx)\nvar opErr *net.OpError\nif errors.As(err, &opErr) && errors.Is(opErr.Err, syscall.EADDRINUSE) {\n    log.Printf(\"proxy port in use, pick another port\")\n}","preventionTips":["Prefer port 0 (OS-assigned) over fixed ports for proxies","Run at most one proxy per rootDir and guard against orphaned processes","Smoke-test loopback bind in restricted environments (containers, CI) before startup"],"tags":["network","tcp","bind","port-in-use"],"backgroundTag":"address-already-in-use","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}