vitessio/vitess · warning

failed to execute logHeader template: %v

Error message

failed to execute logHeader template: %v

What it means

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.

Source

Thrown at go/vt/throttler/throttlerlogz.go:144

	if !slices.Contains(m.Throttlers(), name) {
		http.Error(w, "throttler not found", http.StatusNotFound)
		return
	}

	showThrottlerLog(w, m, name)
}

func showThrottlerLog(w http.ResponseWriter, m *managerImpl, name string) {
	results, err := m.log(name)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	logz.StartHTMLTable(w)

	if _, err := io.WriteString(w, logHeaderHTML); err != nil {
		panic(fmt.Sprintf("failed to execute logHeader template: %v", err))
	}
	for _, r := range results {
		// Color based on max(tested state, new state).
		state := r.TestedState
		if stateGreater(r.NewState, state) {
			state = r.NewState
		}
		var colorLevel string
		switch state {
		case stateIncreaseRate:
			colorLevel = "low"
		case stateDecreaseAndGuessRate:
			colorLevel = "medium"
		case stateEmergency:
			colorLevel = "high"
		}
		data := struct {
			Result

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Reload the debug page; the panic is client-side connection loss, not a throttler fault
  2. If this recurs from a scraper, add write-error tolerance (log and return) instead of panicking in the handler
  3. Check reverse proxy timeout settings against handler generation time

Example fix

// before
if _, err := io.WriteString(w, logHeaderHTML); err != nil {
    panic(fmt.Sprintf("failed to execute logHeader template: %v", err))
}
// after
if _, err := io.WriteString(w, logHeaderHTML); err != nil {
    log.Warnf("client disconnected from throttlerlogz: %v", err)
    return
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before scraping the page, confirm the handler is reachable
resp, err := http.Get(baseURL + "/throttlerlogz")
if err != nil || resp.StatusCode != 200 { return err }

Try / catch

defer func() {
    if r := recover(); r != nil {
        log.Errorf("throttlerlogz handler panic: %v", r)
        http.Error(w, "internal error", http.StatusInternalServerError)
    }
}()

Prevention

When it happens

Trigger: Hitting the /throttlerlogz debug page when the client disconnects or the response writer errors while writing logHeaderHTML.

Common situations: Browser or load balancer closing the debug-page connection early; debugging UI scraped by monitoring that times out mid-response.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/b7926d461dc792f2. Report an issue: GitHub.