vitessio/vitess · warning

failed to write rendered config: %v

Error message

failed to write rendered config: %v

What it means

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.

Source

Thrown at go/viperutil/debug/handler.go:76

		// then copy it to the response.
		//
		// (Sadly, viper does not yet have a WriteConfigTo(w io.Writer), so we have
		// to do this little hacky workaround).
		v.SetConfigType(format)
		tmp, err := os.CreateTemp("", "viper_debug")
		if err != nil {
			http.Error(w, fmt.Sprintf("failed to render config to tempfile: %v", err), http.StatusInternalServerError)
			return
		}
		defer os.Remove(tmp.Name())

		if err := v.WriteConfigAs(tmp.Name()); err != nil {
			http.Error(w, fmt.Sprintf("failed to render config to tempfile: %v", err), http.StatusInternalServerError)
			return
		}

		if _, err := io.Copy(w, tmp); err != nil {
			http.Error(w, fmt.Sprintf("failed to write rendered config: %v", err), http.StatusInternalServerError)
			return
		}
	default:
		http.Error(w, "unsupported config format", http.StatusBadRequest)
	}
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Retry the request and keep the connection open until the response completes.
  2. Increase client/proxy timeouts (e.g. curl --max-time, LB idle timeout).
  3. If large configs hit limits, request a narrower format or subset of the config.
  4. Ignore transient 'broken pipe' occurrences; only investigate if it reproduces with a stable client.

Example fix

// before
curl --max-time 1 'http://localhost:15000/debug/config?format=json'
// after
curl --max-time 30 'http://localhost:15000/debug/config?format=json'
Defensive patterns

Strategy: retry

Try / catch

for attempt := 0; attempt < 3; attempt++ {
	resp, err := http.Get(cfgURL)
	if err != nil {
		time.Sleep(backoff(attempt))
		continue
	}
	body, readErr := io.ReadAll(resp.Body)
	resp.Body.Close()
	if readErr == nil {
		return body, nil
	}
	// read interrupted mid-body: retry
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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