{"record":{"id":"940910ab97513ee7","repo":"vitessio/vitess","slug":"failed-to-write-rendered-config-v","errorCode":null,"errorMessage":"failed to write rendered config: %v","messagePattern":"failed to write rendered config: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"warning","filePath":"go/viperutil/debug/handler.go","lineNumber":76,"sourceCode":"\t\t// then copy it to the response.\n\t\t//\n\t\t// (Sadly, viper does not yet have a WriteConfigTo(w io.Writer), so we have\n\t\t// to do this little hacky workaround).\n\t\tv.SetConfigType(format)\n\t\ttmp, err := os.CreateTemp(\"\", \"viper_debug\")\n\t\tif err != nil {\n\t\t\thttp.Error(w, fmt.Sprintf(\"failed to render config to tempfile: %v\", err), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tdefer os.Remove(tmp.Name())\n\n\t\tif err := v.WriteConfigAs(tmp.Name()); err != nil {\n\t\t\thttp.Error(w, fmt.Sprintf(\"failed to render config to tempfile: %v\", err), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\tif _, err := io.Copy(w, tmp); err != nil {\n\t\t\thttp.Error(w, fmt.Sprintf(\"failed to write rendered config: %v\", err), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\tdefault:\n\t\thttp.Error(w, \"unsupported config format\", http.StatusBadRequest)\n\t}\n}\n","sourceCodeStart":58,"sourceCodeEnd":83,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/viperutil/debug/handler.go#L58-L83","documentation":"After writing the rendered config to the temp file, the handler reads it back with io.Copy(tmp, w) to stream it to the client. If copying to the ResponseWriter fails, it returns 500 'failed to write rendered config'. This is almost always a client-side/connection issue rather than a server bug.","triggerScenarios":"io.Copy(w, tmp) returns an error while streaming the rendered config — typically the HTTP client disconnected mid-response, or the underlying connection was reset/closed before the body completed.","commonSituations":"User closes browser tab or curl with --max-time before the response completes; load balancer timeout cutting the response; network interruption between client and vitess process.","solutions":["Retry the request and keep the connection open until the response completes.","Increase client/proxy timeouts (e.g. curl --max-time, LB idle timeout).","If large configs hit limits, request a narrower format or subset of the config.","Ignore transient 'broken pipe' occurrences; only investigate if it reproduces with a stable client."],"exampleFix":"// before\ncurl --max-time 1 'http://localhost:15000/debug/config?format=json'\n// after\ncurl --max-time 30 'http://localhost:15000/debug/config?format=json'","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for attempt := 0; attempt < 3; attempt++ {\n\tresp, err := http.Get(cfgURL)\n\tif err != nil {\n\t\ttime.Sleep(backoff(attempt))\n\t\tcontinue\n\t}\n\tbody, readErr := io.ReadAll(resp.Body)\n\tresp.Body.Close()\n\tif readErr == nil {\n\t\treturn body, nil\n\t}\n\t// read interrupted mid-body: retry\n}","preventionTips":["Use generous client timeouts (30s+) when fetching debug config endpoints.","Avoid closing the client or killing curl before the response body completes.","Increase LB/proxy idle timeouts for debug endpoints."],"tags":["http","io","broken-pipe","response"],"backgroundTag":"client-disconnected-mid-response","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}