juanfont/headscale · error

creating metrics request: %w

Error message

creating metrics request: %w

What it means

Returned by HeadscaleInContainer.SaveMetrics when constructing the HTTP GET request to http://<container-host>:9090/metrics fails. http.NewRequestWithContext only errors on an invalid method or an unparsable URL, so in practice this fires when the container hostname/port produce a malformed URL.

Source

Thrown at integration/hsic/hsic.go:742

	err := dockertestutil.WriteLog(t.pool, t.container, &stdout, &stderr)
	if err != nil {
		return "", "", fmt.Errorf("reading container logs: %w", err)
	}

	return stdout.String(), stderr.String(), nil
}

// SaveLog saves the current stdout log of the container to a path
// on the host system.
func (t *HeadscaleInContainer) SaveLog(path string) (string, string, error) {
	return dockertestutil.SaveLog(t.pool, t.container, path)
}

func (t *HeadscaleInContainer) SaveMetrics(savePath string) error {
	req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "http://"+net.JoinHostPort(t.hostname, "9090")+"/metrics", nil)
	if err != nil {
		return fmt.Errorf("creating metrics request: %w", err)
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return fmt.Errorf("getting metrics: %w", err)
	}
	defer resp.Body.Close()

	out, err := os.Create(savePath)
	if err != nil {
		return fmt.Errorf("creating file for metrics: %w", err)
	}
	defer out.Close()

	_, err = io.Copy(out, resp.Body)
	if err != nil {
		return fmt.Errorf("copy response to file: %w", err)
	}

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Ensure the headscale container was created and started successfully before calling SaveMetrics (wait for WaitForRunning)
  2. Check that a custom hsic.WithHostname option, if used, supplies a valid DNS name
  3. Inspect the wrapped error — url.Error will name the malformed URL part
Defensive patterns

Strategy: validation

Validate before calling

if headscale.GetHostname() == "" {
    return errors.New("headscale hostname not set; container not ready for metrics scrape")
}

Try / catch

if err := headscale.SaveMetrics(path); err != nil {
    t.Logf("metrics not saved: %v", err) // metrics capture is best-effort diagnostics
}

Prevention

When it happens

Trigger: Calling SaveMetrics(savePath) when t.hostname is empty or contains characters that make "http://"+net.JoinHostPort(t.hostname, "9090")+"/metrics" an invalid URL.

Common situations: HeadscaleInContainer was constructed without a resolvable hostname; the container failed to start and hostname was never set; a custom option overrode the hostname with an invalid value.

Related errors


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/3d645f7c6eacaf7a. Report an issue: GitHub.