slimtoolkit/slim · error

setting write timeout: %v

Error message

setting write timeout: %v

What it means

RoundTrip mirrors the read-timeout step with fcgiBackend.SetWriteTimeout using the transport's WriteTimeout. Failure is wrapped as "setting write timeout: %v". As with the read deadline, this almost always means the freshly dialed connection is no longer viable or cannot support deadlines.

Source

Thrown at pkg/app/master/probe/http/internal/fastcgi.go:100

		envJSON, _ := json.Marshal(env)
		log.Debugf("HTTP probe - FastCGI env - %s", string(envJSON))
	}

	ctx := r.Context()
	dialer := net.Dialer{Timeout: t.DialTimeout}
	fcgiBackend, err := DialWithDialerContext(ctx, network, address, dialer)
	if err != nil {
		// TODO: wrap in a special error type if the dial failed, so retries can happen if enabled
		return nil, fmt.Errorf("dialing backend: %v", err)
	}
	// fcgiBackend gets closed when response body is closed (see clientCloser)

	// read/write timeouts
	if err := fcgiBackend.SetReadTimeout(t.ReadTimeout); err != nil {
		return nil, fmt.Errorf("setting read timeout: %v", err)
	}
	if err := fcgiBackend.SetWriteTimeout(t.WriteTimeout); err != nil {
		return nil, fmt.Errorf("setting write timeout: %v", err)
	}

	contentLength := r.ContentLength
	if contentLength == 0 {
		contentLength, _ = strconv.ParseInt(r.Header.Get("Content-Length"), 10, 64)
	}

	var resp *http.Response
	switch r.Method {
	case http.MethodHead:
		resp, err = fcgiBackend.Head(env)
	case http.MethodGet:
		resp, err = fcgiBackend.Get(env, r.Body, contentLength)
	case http.MethodOptions:
		resp, err = fcgiBackend.Options(env)
	default:
		resp, err = fcgiBackend.Post(env, r.Method, r.Header.Get("Content-Type"), r.Body, contentLength)
	}

View on GitHub (pinned to 81940d17fa)

Solutions

  1. Read the wrapped cause; if deadlines are unsupported on this conn type, disable/raise WriteTimeout.
  2. Verify the FastCGI backend stays alive across the request (no OOM kills, worker exhaustion).
  3. Set an explicit positive WriteTimeout on the transport instead of relying on defaults.
  4. Retry the request — the dial is retryable per code comments, and the failure may be transient.

Example fix

// before
if err := fcgiBackend.SetWriteTimeout(t.WriteTimeout); err != nil { ... } // WriteTimeout = 0
// after
// transport config
t := FastCGITransport{ WriteTimeout: 30 * time.Second }
Defensive patterns

Strategy: retry

Validate before calling

if t.WriteTimeout <= 0 {
    return fmt.Errorf("configure a positive WriteTimeout on FastCGITransport")
}

Try / catch

resp, err := fcgiTransport.RoundTrip(req)
if err != nil && strings.Contains(err.Error(), "setting write timeout") {
    return retryRoundTrip(req) // transient conn drop between deadline calls
}

Prevention

When it happens

Trigger: RoundTrip where SetReadTimeout succeeded but SetWriteTimeout failed — conn dropped between the two calls, or the connection implementation rejects deadline operations (unsupported deadline on some unix/mock conns).

Common situations: Flaky backend connections (worker killed between deadline calls); custom/unix socket transports lacking deadline support; zero or absurdly large WriteTimeout values interacting badly with the underlying conn.

Understand the failure class

Related errors


AI-assisted analysis of slimtoolkit/slim@81940d17fa (2026-08-31). Data as JSON: /api/errors/0c2bda626e93e839. Report an issue: GitHub.