gofiber/fiber · error

unexpected error when trying to remove unix socket file %q:

Error message

unexpected error when trying to remove unix socket file %q: %w

What it means

Emitted by createListener when ListenerNetwork is 'unix' and os.Remove of the configured socket path returns an error other than os.ErrNotExist. Fiber proactively clears a stale socket before binding so a crashed/restarting process can re-claim the address; any removal error that is NOT 'file does not exist' is treated as fatal because the subsequent net.Listen would almost certainly fail too. The wrapped %w preserves the underlying syscall error (EACCES, EISDIR, EBUSY, etc.).

Source

Thrown at listen.go:373

	if cfg.EnablePrefork {
		log.Warn("Prefork isn't supported for custom listeners.")
	}

	return app.server.Serve(ln)
}

// Create listener function.
func (*App) createListener(addr string, tlsConfig *tls.Config, cfg *ListenConfig) (net.Listener, error) {
	if cfg == nil {
		cfg = &ListenConfig{}
	}
	var listener net.Listener
	var err error

	// Remove previously created socket, to make sure it's possible to listen
	if cfg.ListenerNetwork == NetworkUnix {
		if err = os.Remove(addr); err != nil && !os.IsNotExist(err) {
			return nil, fmt.Errorf("unexpected error when trying to remove unix socket file %q: %w", addr, err)
		}
	}

	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

View on GitHub (pinned to 9a4c7e57fe)

Solutions

  1. Identify and stop the prior holder: 'lsof <path>' or 'fuser <path>' then kill the PID, or stop the systemd unit.
  2. Fix ownership/permissions so the current process can remove the file: 'sudo chown $(id -u):$(id -g) <path>' or 'sudo rm <path>'.
  3. Verify the path is a file/socket and not a directory: 'ls -ld <path>' — if 'd', pick a different path.
  4. Ensure the parent directory is writable and not on a read-only mount: 'touch <parent>/__t && rm <parent>/__t'.
  5. Restart the service so createListener can os.Remove cleanly.

Example fix

// before: stale root-owned socket blocks the non-root restart
_ = app.Listen("/var/run/app.sock", fiber.ListenConfig{
  ListenerNetwork: fiber.NetworkUnix,
})

// after: own and clean the path before start, or use a runtime-writable dir
os.Remove("/run/user/app/app.sock") // best-effort; ignore IsNotExist
_ = app.Listen("/run/user/app/app.sock", fiber.ListenConfig{
  ListenerNetwork:      fiber.NetworkUnix,
  UnixSocketFileMode:   0o660,
})
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight: ensure the socket path is clearable by this process.
func preflightUnixSocket(path string) error {
    abs, err := filepath.Abs(path)
    if err != nil {
        return err
    }
    if info, err := os.Stat(abs); err == nil {
        if info.IsDir() {
            return fmt.Errorf("socket path %q is a directory", abs)
        }
        if err := os.Remove(abs); err != nil && !os.IsNotExist(err) {
            return fmt.Errorf("cannot remove stale socket %q: %w", abs, err)
        }
    } else if !os.IsNotExist(err) {
        return err
    }
    // parent dir must be writable
    return os.MkdirAll(filepath.Dir(abs), 0o755)
}

Type guard

null

Try / catch

err := app.Listen(sock, fiber.ListenConfig{ListenerNetwork: fiber.NetworkUnix})
if err != nil {
    var lp *net.OpError
    if errors.As(err, &lp) && strings.Contains(err.Error(), "remove unix socket") {
        // surface as a deployment/permission issue, not a code bug
        log.Errorf("socket pre-clear failed (%v) — check owner/perms of %s", err, sock)
    }
    return err
}

Prevention

When it happens

Trigger: Starting Fiber with app.Listen(NetworkUnix+'/var/run/app.sock', ...) where the path exists and is owned by another uid (EACCES), is a directory (EISDIR), or is held open by a still-running process you don't have permission to unlink. Removing a path on a read-only filesystem or in a directory without write permission also triggers it.

Common situations: Two instances pointed at the same socket where the second lacks privileges; running under a non-root user while the prior run was root (root-owned socket); systemd socket activation leaves a socket file; Docker volume mounted read-only; path typo resolves to an existing directory.

Related errors


AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04). Data as JSON: /data/errors/5ab24ffa8733ca8a.json. Report an issue: GitHub.