gofiber/fiber · error

cannot chmod %#o for

Error message

cannot chmod %#o for %q: %w

What it means

Returned by createListener after a Unix socket listener is successfully created but os.Chmod on the socket path fails. Fiber sets UnixSocketFileMode so cooperating processes can connect; a chmod failure means the socket exists but with default permissions, likely blocking clients. The listener is closed before returning so callers do not get a half-configured socket.

Solutions

  1. Check the runtime allows chmod on the socket directory: strace -e fchmod ./myapp.
  2. Move the socket to a standard runtime directory that supports chmod (e.g. /run/<service>/).
  3. Loosen or fix the seccomp/AppArmor profile to permit fchmod/fchmodat.
  4. Ensure no other process (systemd socket activation, prior instance) is racing the path.
  5. Verify UnixSocketFileMode is a sane permission (typically 0o660 or 0o660).

Example fix

// before: socket on a mount that rejects chmod
app.Listen("/mnt/ro/fiber.sock", fiber.ListenConfig{ListenerNetwork: fiber.NetworkUnix})

// after: socket on a runtime dir that supports chmod
app.Listen("/run/fiber/fiber.sock", fiber.ListenConfig{ListenerNetwork: fiber.NetworkUnix, UnixSocketFileMode: 0o660})
Defensive patterns

Strategy: validation

Validate before calling

func checkUnixSocketChmod(path string, mode os.FileMode) error {
    parent := filepath.Dir(path)
    // verify the parent supports chmod by probing a temp file
    probe := filepath.Join(parent, ".chmod-probe")
    f, err := os.Create(probe)
    if err != nil { return fmt.Errorf("cannot create probe in socket dir: %w", err) }
    _ = f.Close()
    if err := os.Chmod(probe, mode); err != nil {
        _ = os.Remove(probe)
        return fmt.Errorf("chmod not supported in socket dir: %w", err)
    }
    _ = os.Remove(probe)
    return nil
}

Prevention

When it happens

Trigger: UnixSocketFileMode is invalid (note: zero FileMode is a no-op elsewhere but here os.Chmod is invoked unconditionally for unix networks); the socket path was deleted by another process between Listen and Chmod; the filesystem does not support chmod (some FUSE mounts, /proc); EPERM running under a seccomp/AppArmor profile that blocks chmod.

Common situations: Default UnixSocketFileMode of 0o660 is fine on ext4 but a restrictive container runtime blocks chmod; another supervisor (systemd socket activation) raced Fiber to the path; the socket lives on a tmpfs with noexec/nodev that also rejects mode changes; misconfigured seccomp in Docker blocking the fchmod syscall.

Related errors


AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11). Data as JSON: /api/errors/a3c2a416de6d61dc. Report an issue: GitHub.

Appendix: source

Thrown at listen.go:487

		}
	}

	if tlsConfig != nil {
		listener, err = tls.Listen(cfg.ListenerNetwork, addr, tlsConfig)
	} else {
		listener, err = net.Listen(cfg.ListenerNetwork, addr)
	}

	// Check for error before using the listener
	if err != nil {
		// Wrap the error from tls.Listen/net.Listen
		return nil, fmt.Errorf("failed to listen: %w", err)
	}

	if cfg.ListenerNetwork == NetworkUnix {
		if err = os.Chmod(addr, cfg.UnixSocketFileMode); err != nil {
			_ = listener.Close() //nolint:errcheck // best-effort cleanup on the error path
			return nil, fmt.Errorf("cannot chmod %#o for %q: %w", cfg.UnixSocketFileMode, addr, err)
		}
	}

	if cfg.ListenerAddrFunc != nil {
		cfg.ListenerAddrFunc(listener.Addr())
	}

	return listener, nil
}

func (app *App) printMessages(cfg *ListenConfig, listenData *ListenData) {
	app.startupMessage(listenData, cfg)

	if cfg.EnablePrintRoutes {
		app.printRoutesMessage()
	}
}

View on GitHub (pinned to a105acad6c)