kataras/iris · error
cannot chmod %#o for %q: %w
Error message
cannot chmod %#o for %q: %w
What it means
netutil.UNIX wraps net.Listen on a unix socket path, then adjusts the socket file's permission bits with os.Chmod. If the chmod fails (e.g. the file vanished, wrong owner, or unsupported by the filesystem), the listen call is abandoned and this wrapped error is returned, preserving the underlying cause via %w.
Source
Thrown at core/netutil/tcp.go:80
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")
}
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, err
}
return CERT(addr, cert)
}View on GitHub (pinned to 7bedaf55a0)
Solutions
- Check the wrapped cause (%w) — fix the underlying os.Chmod error (ownership, missing file, unsupported filesystem)
- Run the process with enough privilege to chmod the socket file, or pre-create the directory with correct owner/permissions
- Move the socket file to a local filesystem path such as /tmp or /run where chmod is supported
- Ensure no cleanup process deletes the socket file between listen and chmod
Example fix
// before
l, err := netutil.UNIX("/mnt/nfs/app.sock", 0o755)
// after
l, err := netutil.UNIX("/run/myapp/app.sock", 0o755) Defensive patterns
Strategy: validation
Validate before calling
if fi, err := os.Stat(socketFile); err == nil {
if fi.Mode()&os.ModeSocket == 0 { return fmt.Errorf("%s exists and is not a socket", socketFile) }
os.Remove(socketFile)
}
if err := os.MkdirAll(filepath.Dir(socketFile), 0o755); err != nil { return err } Type guard
func canChmod(path string) bool {
fi, err := os.Stat(path)
return err == nil && fi.Mode().Perm() != 0
} Try / catch
l, err := netutil.UNIX(socketFile, 0o755)
if err != nil {
var perr *fs.PathError
if errors.As(err, &perr) { log.Printf("chmod failed: %v", perr.Err) }
return err
} Prevention
- Place unix sockets on local filesystems (/run, /tmp), not NFS or bind mounts
- Pre-create the socket directory with correct ownership before startup
- Run the service under a user that owns the socket directory
- Watch out for systemd tmpfiles or cleanup jobs deleting stale sockets at startup
When it happens
Trigger: Calling netutil.UNIX with a socketFile on a filesystem that does not support chmod semantics (some NFS/network mounts, tmpfs with restrictions), a file system where the process lacks ownership of the freshly created socket, or the socket file being removed between Listen and Chmod.
Common situations: Running the app in a container as non-root while the socket directory has restrictive permissions; deploying to read-only or quirky mounted volumes (Docker bind mounts, NFS); socket path inside a directory cleaned up by another process mid-startup.
Related errors
- %s: %w
- dest directory: %s: eval symlinks: %w
- err
- err
- auth: configuration: %s access token is missing from the con
AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30).
Data as JSON: /api/errors/9784223f9252eb9a.
Report an issue: GitHub.