vitessio/vitess · warning
err.Error() (Fprintf write failure)
Error message
err.Error() (Fprintf write failure)
What it means
After executing the stats template, WriteScatterStats appends a summary line via fmt.Fprintf to the response. If that write fails (client gone, connection reset), the raw error is passed to http.Error with a 500. Because headers/body are already sent, the 500 cannot change the status code; the error text is effectively only visible in logs or as garbage in the stream.
Source
Thrown at go/vt/vtgate/executor_scatter_stats.go:138
http.Error(w, err.Error(), 500)
return
}
t := template.New("template")
t, err = t.Parse(statsHTML)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
err = t.Execute(w, results)
if err != nil {
http.Error(w, err.Error(), 500)
}
_, err = fmt.Fprintf(w, "Percentage of time spent on scatter queries: %2.2f%%", results.PercentTimeScatter)
if err != nil {
http.Error(w, err.Error(), 500)
}
}
const statsHTML = `
<thead>
<tr>
<th>Query</th>
<th># of executions</th>
<th>Avg time/query</th>
<th>% time of reads</th>
<th>% time of scatters</th>
<th>% of reads</th>
<th>% of scatters</th>
</tr>
</thead>
{{range .Items}}
<tr class="medium">
<td>{{.Query}}</td>View on GitHub (pinned to 01a25a7d17)
Solutions
- Retry the debug request with a stable connection
- Check vtgate logs for the write error; treat client-disconnect errors as benign noise
- Increase any client/proxy read timeouts that cut the response short
Defensive patterns
Strategy: fallback
Validate before calling
resp, err := http.Get("http://vtgate:15001/scatterStats")
if err != nil {
// connection failed before write; use fallback stats source
} Try / catch
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Warn("partial scatterStats read", slog.Any("error", err))
} Prevention
- Use adequate client timeouts so the response finishes streaming
- Reconnect-and-retry scrapers instead of dropping mid-response
- Treat trailing-write errors on already-committed responses as benign
- Pull PercentTimeScatter from metrics endpoints when available
When it happens
Trigger: Calling the /scatterStats debug endpoint when the HTTP connection is broken or closed before the final Fprintf write completes.
Common situations: Client (curl/browser/monitoring scraper) disconnects during streaming of the stats page; response already committed so http.Error is a no-op on status.
Related errors
- err.Error() (template execute failure)
- can't get %v: %v
- throttler not found
- cell mode should be handled by the gateway, not the balancer
- both the dry-run mode and actual buffering is enabled. To av
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/e8a37d846565e4bd.
Report an issue: GitHub.