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
- Read the wrapped cause; if deadlines are unsupported on this conn type, disable/raise WriteTimeout.
- Verify the FastCGI backend stays alive across the request (no OOM kills, worker exhaustion).
- Set an explicit positive WriteTimeout on the transport instead of relying on defaults.
- 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
- Configure an explicit positive WriteTimeout instead of defaults/zero.
- Treat single failed RoundTrip as transient: retry once before surfacing.
- Ensure the FastCGI backend remains healthy (no restarts mid-request).
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- setting read timeout: %v
- fcgi: invalid header version
- building environment: %v
- dialing backend: %v
- start monitor timeout
AI-assisted analysis of slimtoolkit/slim@81940d17fa (2026-08-31).
Data as JSON: /api/errors/0c2bda626e93e839.
Report an issue: GitHub.