cloudreve/cloudreve · error

send request failed: %w

Error message

send request failed: %w

What it means

The request client set res.Err before an HTTP status existed - a transport-level failure: DNS resolution failure, connection refused, TLS handshake error, dial/read timeout, or a canceled context. Every qbittorrentClient call (Info, CreateTask, Cancel, Test, setFilePriority) funnels through this wrapper.

Source

Thrown at pkg/downloader/qbittorrent/qbittorrent.go:370

		return fmt.Errorf("login failed with response: %s, possibly inccorrect credential is provided", res)
	}

	return nil
}

func (c *qbittorrentClient) request(ctx context.Context, method, path string, body string, headers *http.Header) (string, error) {
	opts := []request.Option{
		request.WithContext(ctx),
	}

	if headers != nil {
		opts = append(opts, request.WithHeader(*headers))
	}

	res := c.c.Request(method, path, strings.NewReader(body), opts...)

	if res.Err != nil {
		return "", fmt.Errorf("send request failed: %w", res.Err)
	}

	switch res.Response.StatusCode {
	case http.StatusForbidden:
		c.l.Info("QBittorrent cookie expired, sending login request...")
		if err := c.login(ctx); err != nil {
			return "", fmt.Errorf("login failed: %w", err)
		}

		return c.request(ctx, method, path, body, headers)

	case http.StatusOK:
		respContent, err := res.GetResponse()
		if err != nil {
			return "", fmt.Errorf("failed reading response: %w", err)
		}

		return respContent, nil

View on GitHub (pinned to 20c95ad73f)

Solutions

  1. Verify host:port reachability from the Cloudreve machine (curl or nc)
  2. Fix the scheme (http vs https) and port in the node settings
  3. For TLS failures, use a valid certificate or switch to plain http on a trusted network
  4. For context-canceled errors, review the caller's timeout/deadline budget
Defensive patterns

Strategy: retry

Validate before calling

// Cheap reachability probe before long operations
conn, err := net.DialTimeout("tcp", hostPort(cfg.Server), 3*time.Second)
if err != nil {
    return fmt.Errorf("qbittorrent unreachable: %w", err)
}
conn.Close()

Type guard

func isTransportError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "send request failed")
}

Try / catch

res, err := op(ctx)
if isTransportError(err) && !errors.Is(err, context.Canceled) {
    time.Sleep(backoff)
    res, err = op(ctx) // one bounded retry on a fresh connection
}
if err != nil {
    return err
}

Prevention

When it happens

Trigger: Any of those calls while the qBittorrent server is unreachable, the TLS certificate is invalid for https URLs, the port is wrong, a deadline expires, or the passed context is canceled mid-request.

Common situations: qBittorrent service down or restarting; firewall blocking the port; self-signed cert without trust; Cloudreve shutting down and canceling in-flight contexts; transient DNS hiccups in container environments.

Related errors


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