kataras/iris · error

%s: %w

Error message

%s: %w

What it means

netutil.UNIX removes any existing socket file before listening; if os.Remove fails with an error other than "not exist" (e.g. permission denied, path is a directory), the error is wrapped with the socket path and returned.

Source

Thrown at core/netutil/tcp.go:71

func TCPKeepAlive(addr string, reuse bool, keepAliveDur time.Duration) (ln net.Listener, err error) {
	// if strings.HasPrefix(addr, "127.0.0.1") {
	// 	// it's ipv4, use ipv4 tcp listener instead of the default ipv6. Don't.
	// 	ln, err = net.Listen("tcp4", addr)
	// } else {
	// 	ln, err = TCP(addr)
	// }

	ln, err = TCP(addr, reuse)
	if err != nil {
		return nil, err
	}
	return tcpKeepAliveListener{ln.(*net.TCPListener), keepAliveDur}, nil
}

// UNIX returns a new unix(file) Listener.
func UNIX(socketFile string, mode os.FileMode) (net.Listener, error) {
	if errOs := os.Remove(socketFile); errOs != nil && !os.IsNotExist(errOs) {
		return nil, fmt.Errorf("%s: %w", socketFile, errOs)
	}

	l, err := net.Listen("unix", socketFile)
	if err != nil {
		return nil, fmt.Errorf("port already in use: %w", err)
	}

	if err = os.Chmod(socketFile, mode); err != nil {
		return nil, fmt.Errorf("cannot chmod %#o for %q: %w", mode, socketFile, err)
	}

	return l, nil
}

// TLS returns a new TLS Listener and an error on failure.
func TLS(addr, certFile, keyFile string) (net.Listener, error) {
	if certFile == "" || keyFile == "" {
		return nil, errors.New("empty certFile or KeyFile")

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Ensure the directory containing the socket is writable by the process user and that socketFile is not a directory.
  2. Manually remove the stale socket file before starting, or run under a user that can.
  3. Point UNIX() to a fresh path in a writable temp/run directory (e.g. /run/myapp/app.sock).

Example fix

// before
ln, _ := netutil.UNIX("/var/run/app.sock", 0666) // permission denied
// after
ln, _ := netutil.UNIX("/run/myapp/app.sock", 0666) // dir owned by app user
Defensive patterns

Strategy: validation

Validate before calling

if fi, err := os.Stat(socketFile); err == nil && fi.IsDir() {
    return errors.New("socket path is a directory")
}
// ensure parent dir is writable
if err := os.MkdirAll(filepath.Dir(socketFile), 0755); err != nil {
    return err
}

Try / catch

ln, err := netutil.UNIX(socketFile, mode)
if err != nil {
    if !os.IsNotExist(err) && strings.Contains(err.Error(), socketFile) {
        os.RemoveAll(socketFile) // only if safe
        ln, err = netutil.UNIX(socketFile, mode)
    }
}

Prevention

When it happens

Trigger: Calling netutil.UNIX(socketFile, mode) where socketFile exists but cannot be removed: read-only directory, the path is a directory rather than a socket, or another user owns it.

Common situations: Stale socket left by a crashed process owned by another user; pointing socketFile at a directory; running the app as a non-root user after a previous root run.

Related errors


AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30). Data as JSON: /api/errors/cc799dfaf4cbef2f. Report an issue: GitHub.