{"record":{"id":"b7926d461dc792f2","repo":"vitessio/vitess","slug":"failed-to-execute-logheader-template-v","errorCode":null,"errorMessage":"failed to execute logHeader template: %v","messagePattern":"failed to execute logHeader template: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"go/vt/throttler/throttlerlogz.go","lineNumber":144,"sourceCode":"\tif !slices.Contains(m.Throttlers(), name) {\n\t\thttp.Error(w, \"throttler not found\", http.StatusNotFound)\n\t\treturn\n\t}\n\n\tshowThrottlerLog(w, m, name)\n}\n\nfunc showThrottlerLog(w http.ResponseWriter, m *managerImpl, name string) {\n\tresults, err := m.log(name)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tlogz.StartHTMLTable(w)\n\n\tif _, err := io.WriteString(w, logHeaderHTML); err != nil {\n\t\tpanic(fmt.Sprintf(\"failed to execute logHeader template: %v\", err))\n\t}\n\tfor _, r := range results {\n\t\t// Color based on max(tested state, new state).\n\t\tstate := r.TestedState\n\t\tif stateGreater(r.NewState, state) {\n\t\t\tstate = r.NewState\n\t\t}\n\t\tvar colorLevel string\n\t\tswitch state {\n\t\tcase stateIncreaseRate:\n\t\t\tcolorLevel = \"low\"\n\t\tcase stateDecreaseAndGuessRate:\n\t\t\tcolorLevel = \"medium\"\n\t\tcase stateEmergency:\n\t\t\tcolorLevel = \"high\"\n\t\t}\n\t\tdata := struct {\n\t\t\tResult","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/throttler/throttlerlogz.go#L126-L162","documentation":"The throttler log debug HTTP handler (showThrottlerLog) writes a pre-parsed HTML header template (logHeaderHTML) to the response with io.WriteString; any write failure to the HTTP response writer is treated as unrecoverable and panics inside the handler. This typically means the HTTP client connection died mid-response.","triggerScenarios":"Hitting the /throttlerlogz debug page when the client disconnects or the response writer errors while writing logHeaderHTML.","commonSituations":"Browser or load balancer closing the debug-page connection early; debugging UI scraped by monitoring that times out mid-response.","solutions":["Reload the debug page; the panic is client-side connection loss, not a throttler fault","If this recurs from a scraper, add write-error tolerance (log and return) instead of panicking in the handler","Check reverse proxy timeout settings against handler generation time"],"exampleFix":"// before\nif _, err := io.WriteString(w, logHeaderHTML); err != nil {\n    panic(fmt.Sprintf(\"failed to execute logHeader template: %v\", err))\n}\n// after\nif _, err := io.WriteString(w, logHeaderHTML); err != nil {\n    log.Warnf(\"client disconnected from throttlerlogz: %v\", err)\n    return\n}","handlingStrategy":"try-catch","validationCode":"// before scraping the page, confirm the handler is reachable\nresp, err := http.Get(baseURL + \"/throttlerlogz\")\nif err != nil || resp.StatusCode != 200 { return err }","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Errorf(\"throttlerlogz handler panic: %v\", r)\n        http.Error(w, \"internal error\", http.StatusInternalServerError)\n    }\n}()","preventionTips":["Wrap debug handlers with a recover middleware","Avoid scraping debug pages with aggressive timeouts","Increase proxy read timeouts for debug endpoints"],"tags":["go","panic","http-handler","debug-page"],"backgroundTag":"http-client-disconnect","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}