wavetermdev/waveterm · error
error creating listener at %v: %v
Error message
error creating listener at %v: %v
What it means
Returned by MakeRemoteUnixListener when net.Listen("unix", serverAddr) fails while creating the remote wsh domain socket. The path is derived from getRemoteDomainSocketName() and any stale socket is removed first; failure means the OS refused to bind the unix socket at that path.
Source
Thrown at cmd/wsh/cmd/wshcmd-connserver.go:127
defer ticker.Stop()
for range ticker.C {
cleanupOldJobLogs()
}
}()
}
func getRemoteDomainSocketName() string {
homeDir := wavebase.GetHomeDir()
return filepath.Join(homeDir, wavebase.RemoteWaveHomeDirName, wavebase.RemoteDomainSocketBaseName)
}
func MakeRemoteUnixListener() (net.Listener, error) {
serverAddr := getRemoteDomainSocketName()
os.Remove(serverAddr) // ignore error
rtn, err := net.Listen("unix", serverAddr)
if err != nil {
return nil, fmt.Errorf("error creating listener at %v: %v", serverAddr, err)
}
os.Chmod(serverAddr, 0700)
log.Printf("Server [unix-domain] listening on %s\n", serverAddr)
return rtn, nil
}
func handleNewListenerConn(conn net.Conn, router *wshutil.WshRouter) {
defer func() {
panichandler.PanicHandler("handleNewListenerConn", recover())
}()
var linkIdContainer atomic.Int32
proxy := wshutil.MakeRpcProxy(fmt.Sprintf("connserver:%s", conn.RemoteAddr().String()))
go func() {
defer func() {
panichandler.PanicHandler("handleNewListenerConn:AdaptOutputChToStream", recover())
}()
writeErr := wshutil.AdaptOutputChToStream(proxy.ToRemoteCh, conn)
if writeErr != nil {View on GitHub (pinned to a4447c1563)
Solutions
- Check whether another process is bound to the socket (`ss -x | grep <sockname>` or lsof) and kill the stale holder
- Ensure the socket's parent directory exists and is writable by the current user
- Shorten the socket path if it exceeds the ~108-char unix socket limit
- Remove a stale socket file manually if os.Remove failed (e.g. permissions) and retry
Example fix
// before
os.Remove(serverAddr) // ignore error
rtn, err := net.Listen("unix", serverAddr)
// after
if dir := filepath.Dir(serverAddr); dir != "." {
os.MkdirAll(dir, 0700)
}
os.Remove(serverAddr)
rtn, err := net.Listen("unix", serverAddr) Defensive patterns
Strategy: fallback
Validate before calling
sockDir := filepath.Dir(getRemoteDomainSocketName())
if info, err := os.Stat(sockDir); err != nil || !info.IsDir() {
os.MkdirAll(sockDir, 0700)
}
if len(serverAddr) >= 108 {
return fmt.Errorf("socket path too long (%d chars): %s", len(serverAddr), serverAddr)
} Try / catch
ln, err := MakeRemoteUnixListener()
if err != nil {
var oe *net.OpError
if errors.As(err, &oe) && os.IsExist(oe.Err) {
os.Remove(getRemoteDomainSocketName())
ln, err = MakeRemoteUnixListener() // retry once after removing stale socket
}
if err != nil {
return err
}
} Prevention
- Ensure the socket directory exists and is writable before startup
- Keep socket paths short (under ~108 chars)
- Clean up stale sockets on shutdown and on startup
- Run only one connserver instance per user/host
When it happens
Trigger: The socket path's parent directory does not exist, the path exceeds unix socket path limits (108 bytes), permission denied on the directory, or the address is already in use by a live process.
Common situations: Running the connserver in a container/sandbox with a read-only or missing temp dir, another wshserver instance still holding the socket, overly restrictive permissions, deeply nested paths making the socket name too long.
Related errors
- cannot create unix listener: %v
- failed to create socket directory: %w
- failed to listen on domain socket: %w
- accessing file %s: %w
- reading directory %s: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/5bd3e36ecc198588.
Report an issue: GitHub.