yudai/gotty · error
failed to listen at `%s`
Error message
failed to listen at `%s`
What it means
Run() calls net.Listen("tcp", address:port) to bind the listener. If the OS refuses the bind (port in use, permission denied, invalid address), the error is wrapped with the host:port that failed. GoTTY exits and no server is started.
Source
Thrown at server/server.go:122
srv, err := server.setupHTTPServer(handlers)
if err != nil {
return errors.Wrapf(err, "failed to setup an HTTP server")
}
if server.options.PermitWrite {
log.Printf("Permitting clients to write input to the PTY.")
}
if server.options.Once {
log.Printf("Once option is provided, accepting only one client")
}
if server.options.Port == "0" {
log.Printf("Port number configured to `0`, choosing a random port")
}
hostPort := net.JoinHostPort(server.options.Address, server.options.Port)
listener, err := net.Listen("tcp", hostPort)
if err != nil {
return errors.Wrapf(err, "failed to listen at `%s`", hostPort)
}
scheme := "http"
if server.options.EnableTLS {
scheme = "https"
}
host, port, _ := net.SplitHostPort(listener.Addr().String())
log.Printf("HTTP server is listening at: %s", scheme+"://"+host+":"+port+path)
if server.options.Address == "0.0.0.0" {
for _, address := range listAddresses() {
log.Printf("Alternative URL: %s", scheme+"://"+address+":"+port+path)
}
}
srvErr := make(chan error, 1)
go func() {
if server.options.EnableTLS {
crtFile := homedir.Expand(server.options.TLSCrtFile)View on GitHub (pinned to a080c85cbc)
Solutions
- Choose a free port (or port "0" to let GoTTY pick a random one)
- Stop the process occupying the port (lsof -i :PORT / netstat)
- Use address 0.0.0.0 or 127.0.0.1 instead of an unassigned interface address
- For privileged ports, run with root/cap_net_bind_service or use a high port
Example fix
// before port = "80" // after port = "8080"
Defensive patterns
Strategy: retry
Validate before calling
func portFree(addr, port string) bool {
ln, err := net.Listen("tcp", net.JoinHostPort(addr, port))
if err != nil { return false }
ln.Close()
return true
} Try / catch
if err := srv.Run(ctx); err != nil {
var nerr *net.OpError
if errors.As(err, &nerr) {
// address already in use / permission denied — pick another port
}
} Prevention
- Use port "0" or an ephemeral high port in shared environments
- Check port availability before starting; avoid fixed privileged ports
- Bind 0.0.0.0/127.0.0.1 rather than specific interface IPs
When it happens
Trigger: Calling Run() when options.Port is already bound by another process, below 1024 without privileges, or options.Address is not a local IP/hostname.
Common situations: Another GoTTY or web server already on port 8080; running in a container without the port mapped/allowed; address typo like 0.0.0.0 vs an unassigned interface IP; port 80/443 without root (or setcap).
AI-assisted analysis of yudai/gotty@a080c85cbc (2026-09-02).
Data as JSON: /api/errors/b0677bcd35a76ced.
Report an issue: GitHub.