cloudreve/cloudreve · critical

failed to delete socket file %q: %w

Error message

failed to delete socket file %q: %w

What it means

Returned during Unix-socket boot when a stale socket file exists at the configured path but os.Remove fails. The server proactively deletes the leftover socket before listening (a bound socket file from a crashed previous run would make Listen fail with 'address already in use'), and this error means the cleanup itself could not complete.

Source

Thrown at application/application.go:162

	}

	// 如果启用了SSL
	if s.config.SSL().CertPath != "" {
		s.logger.Info("Listening to %q", s.config.SSL().Listen)
		s.server.Addr = s.config.SSL().Listen
		if err := s.server.ListenAndServeTLS(s.config.SSL().CertPath, s.config.SSL().KeyPath); err != nil && !errors.Is(err, http.ErrServerClosed) {
			return fmt.Errorf("failed to listen to %q: %w", s.config.SSL().Listen, err)
		}

		return nil
	}

	// 如果启用了Unix
	if s.config.Unix().Listen != "" {
		// delete socket file before listening
		if _, err := os.Stat(s.config.Unix().Listen); err == nil {
			if err = os.Remove(s.config.Unix().Listen); err != nil {
				return fmt.Errorf("failed to delete socket file %q: %w", s.config.Unix().Listen, err)
			}
		}

		s.logger.Info("Listening to %q", s.config.Unix().Listen)
		if err := s.runUnix(s.server); err != nil && !errors.Is(err, http.ErrServerClosed) {
			return fmt.Errorf("failed to listen to %q: %w", s.config.Unix().Listen, err)
		}

		return nil
	}

	s.logger.Info("Listening to %q", s.config.System().Listen)
	s.server.Addr = s.config.System().Listen
	if err := s.server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
		return fmt.Errorf("failed to listen to %q: %w", s.config.System().Listen, err)
	}
	return nil
}

View on GitHub (pinned to 20c95ad73f)

Solutions

  1. Check the wrapped error for EACCES/EISDIR/EROFS to identify the cause
  2. Manually remove the stale file: rm /path/to/cloudreve.sock, or fix ownership so the service user can unlink it
  3. If the path is a directory, correct the Unix.Listen value in conf
  4. Ensure the service user owns the socket's parent directory

Example fix

# before: stale socket owned by root, service runs as cloudreve
# boot fails: failed to delete socket file

# after
sudo rm /run/cloudreve.sock && sudo chown cloudreve /run && systemctl start cloudreve
Defensive patterns

Strategy: validation

Validate before calling

// Clean/verify the socket path before boot
if p := cfg.Unix().Listen; p != "" {
    if fi, err := os.Stat(p); err == nil {
        if fi.IsDir() {
            return fmt.Errorf("socket path %q is a directory", p)
        }
        if err := os.Remove(p); err != nil {
            return fmt.Errorf("cannot remove stale socket (check ownership): %w", err)
        }
    }
}

Prevention

When it happens

Trigger: config Unix().Listen is set, the file at that path exists (previous unclean shutdown), and the process lacks write/parent-directory permission to remove it, or the path is actually a directory.

Common situations: Running the service under a different, unprivileged user than the one that created the socket; socket path on a read-only mount; path accidentally created as a directory (bad config or manual mistake); SELinux/AppArmor denying unlink.

Related errors


AI-assisted analysis of cloudreve/cloudreve@20c95ad73f (2026-08-16). Data as JSON: /api/errors/0f28fde7ce695086. Report an issue: GitHub.