{"record":{"id":"ce1742954740bfb4","repo":"slimtoolkit/slim","slug":"setting-read-timeout-v","errorCode":null,"errorMessage":"setting read timeout: %v","messagePattern":"setting read timeout: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/app/master/probe/http/internal/fastcgi.go","lineNumber":97,"sourceCode":"\tnetwork, address := \"tcp\", r.URL.Host\n\n\tif log.IsLevelEnabled(log.DebugLevel) {\n\t\tenvJSON, _ := json.Marshal(env)\n\t\tlog.Debugf(\"HTTP probe - FastCGI env - %s\", string(envJSON))\n\t}\n\n\tctx := r.Context()\n\tdialer := net.Dialer{Timeout: t.DialTimeout}\n\tfcgiBackend, err := DialWithDialerContext(ctx, network, address, dialer)\n\tif err != nil {\n\t\t// TODO: wrap in a special error type if the dial failed, so retries can happen if enabled\n\t\treturn nil, fmt.Errorf(\"dialing backend: %v\", err)\n\t}\n\t// fcgiBackend gets closed when response body is closed (see clientCloser)\n\n\t// read/write timeouts\n\tif err := fcgiBackend.SetReadTimeout(t.ReadTimeout); err != nil {\n\t\treturn nil, fmt.Errorf(\"setting read timeout: %v\", err)\n\t}\n\tif err := fcgiBackend.SetWriteTimeout(t.WriteTimeout); err != nil {\n\t\treturn nil, fmt.Errorf(\"setting write timeout: %v\", err)\n\t}\n\n\tcontentLength := r.ContentLength\n\tif contentLength == 0 {\n\t\tcontentLength, _ = strconv.ParseInt(r.Header.Get(\"Content-Length\"), 10, 64)\n\t}\n\n\tvar resp *http.Response\n\tswitch r.Method {\n\tcase http.MethodHead:\n\t\tresp, err = fcgiBackend.Head(env)\n\tcase http.MethodGet:\n\t\tresp, err = fcgiBackend.Get(env, r.Body, contentLength)\n\tcase http.MethodOptions:\n\t\tresp, err = fcgiBackend.Options(env)","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/slimtoolkit/slim/blob/81940d17fa112cc678e32209214bcb2355cb3004/pkg/app/master/probe/http/internal/fastcgi.go#L79-L115","documentation":"After dialing the FastCGI backend, RoundTrip applies the transport's ReadTimeout via fcgiBackend.SetReadTimeout. If the connection cannot accept the timeout (typically because the connection is already broken/closed), the error is wrapped as \"setting read timeout: %v\". The backend conn is usable only if both read and write timeouts apply cleanly.","triggerScenarios":"RoundTrip where SetReadTimeout fails right after a successful dial — usually the underlying conn is dead (peer reset immediately), or the conn type does not support deadline setting (e.g. certain mock/unix conns).","commonSituations":"Backend accepting then instantly closing the connection (crashing php-fpm worker); DialTimeout succeeding but the conn being torn down before deadlines are set; unusual network stacks where deadlines are unsupported.","solutions":["Inspect the wrapped error for an os.ErrDeadlineUnsupported / 'not supported' cause and remove or adjust ReadTimeout if deadlines aren't supported.","Check the backend for immediate disconnects (php-fpm logs, container restarts).","Retest connectivity — this often masks a race where the backend died between dial and timeout setup.","Set a sane positive ReadTimeout (not zero/negative) on the transport."],"exampleFix":"// before\nt := FastCGITransport{ DialTimeout: time.Second } // ReadTimeout unset/zero\n// after\nt := FastCGITransport{ DialTimeout: time.Second, ReadTimeout: 30 * time.Second, WriteTimeout: 30 * time.Second }","handlingStrategy":"retry","validationCode":"// only fail on genuinely unsupported deadlines\nif err := fcgiBackend.SetReadTimeout(t.ReadTimeout); err != nil {\n    if errors.Is(err, os.ErrDeadlineUnsupported) {\n        log.Warn(\"deadlines unsupported on this conn; continuing\")\n    } else {\n        return err\n    }\n}","typeGuard":null,"tryCatchPattern":"resp, err := fcgiTransport.RoundTrip(req)\nif err != nil && strings.Contains(err.Error(), \"setting read timeout\") {\n    if !errors.Is(errors.Unwrap(err), os.ErrDeadlineUnsupported) {\n        return retryRoundTrip(req) // likely transient conn death\n    }\n}","preventionTips":["Set explicit positive ReadTimeout/WriteTimeout values on the transport.","Watch for backends that accept then immediately close (worker crashes) — fix that first.","Check backend logs for OOM kills or worker exhaustion causing dead connections."],"tags":["fastcgi","timeout","http-probe"],"backgroundTag":"set-deadline-failed","analyzedSha":"81940d17fa112cc678e32209214bcb2355cb3004","analyzedAt":"2026-08-31T23:06:12.682Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}