rqlite/rqlite · error

error creating HTTP request: %w

Error message

error creating HTTP request: %w

What it means

HTTPSink.Write builds a POST request to the webhook endpoint with http.NewRequest before transmitting. If the request cannot be constructed — invalid URL in the endpoint, or malformed payload reader semantics — the error is wrapped as "error creating HTTP request". This happens before any network I/O.

Source

Thrown at cdc/sink.go:81

func NewHTTPSink(endpoint string, tlsConfig *tls.Config, timeout time.Duration) *HTTPSink {
	httpClient := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: tlsConfig,
		},
		Timeout: timeout,
	}

	return &HTTPSink{
		endpoint:   endpoint,
		httpClient: httpClient,
	}
}

// Write writes the data to the HTTP endpoint.
func (d *HTTPSink) Write(p []byte) (n int, err error) {
	req, err := http.NewRequest("POST", d.endpoint, bytes.NewReader(p))
	if err != nil {
		return 0, fmt.Errorf("error creating HTTP request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")

	resp, err := d.httpClient.Do(req)
	if err != nil {
		return 0, fmt.Errorf("error sending HTTP request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted {
		return 0, fmt.Errorf("HTTP request failed with status %d", resp.StatusCode)
	}
	return len(p), nil
}

// Close releases resources held by the HTTP client.
func (d *HTTPSink) Close() error {
	if d.httpClient != nil {

View on GitHub (pinned to 7586a4d1bd)

Solutions

  1. Validate the endpoint with net/url.Parse before configuring the sink: parse errors pinpoint the bad component.
  2. Fix the CDC Endpoint configuration to a well-formed http(s) URL.
  3. Check for stray whitespace/CR-LF in the endpoint value coming from env vars or config files.
  4. Add a startup check that does a dry-run request creation so misconfiguration fails fast.

Example fix

// before
u, _ := url.Parse(strings.TrimSpace(os.Getenv("CDC_ENDPOINT")))
sink, _ := NewSink(SinkConfig{Endpoint: " http://bad url"})
// after
u, err := url.Parse(strings.TrimSpace(os.Getenv("CDC_ENDPOINT")))
if err != nil || u.Scheme == "" || u.Host == "" {
    return fmt.Errorf("invalid CDC endpoint %q", os.Getenv("CDC_ENDPOINT"))
}
sink, err := NewSink(SinkConfig{Endpoint: u.String()})
Defensive patterns

Strategy: validation

Validate before calling

func validURL(raw string) bool {
    u, err := url.Parse(raw)
    return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
}

Try / catch

_, err := http.NewRequest(http.MethodPost, endpoint, bytes.NewReader(payload))
if err != nil {
    var uerr *url.Error
    if errors.As(err, &uerr) {
        return fmt.Errorf("webhook endpoint %q invalid: %v", endpoint, uerr.Err)
    }
    return err
}

Prevention

When it happens

Trigger: The sink's configured endpoint URL is invalid at request-build time (unparseable URL, unsupported scheme like "ftp://", or bad host characters) — http.NewRequest returns a *url.Error which is wrapped here.

Common situations: CDC config endpoint with typos, spaces, or control characters; environment variable expansion inserting invalid characters; endpoint validated at construction but mutated afterwards.

Related errors


AI-assisted analysis of rqlite/rqlite@7586a4d1bd (2026-09-03). Data as JSON: /api/errors/d1e546684b044559. Report an issue: GitHub.