charmbracelet/crush · error

failed to create request for provider %s: %w

Error message

failed to create request for provider %s: %w

What it means

Wraps an error from http.NewRequestWithContext while building the probe request used to validate a provider's API key. Since the method and body are constants, this almost always means the target URL is invalid (unparseable). The provider ID is included to identify which configured endpoint caused it.

Source

Thrown at internal/config/config.go:1020

		if strings.HasPrefix(apiKey, "ABSK") { // Bedrock API keys
			return nil
		}
		return errors.New("not a valid bedrock api key")
	case catwalk.TypeVercel:
		// NOTE: Vercel does not validate API keys on the `/models` endpoint.
		if strings.HasPrefix(apiKey, "vck_") { // Vercel API keys
			return nil
		}
		return errors.New("not a valid vercel api key")
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	client := &http.Client{}
	req, err := http.NewRequestWithContext(ctx, "GET", testURL, nil)
	if err != nil {
		return fmt.Errorf("failed to create request for provider %s: %w", c.ID, err)
	}
	for k, v := range headers {
		req.Header.Set(k, v)
	}
	for k, v := range c.ExtraHeaders {
		req.Header.Set(k, v)
	}

	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("failed to create request for provider %s: %w", c.ID, err)
	}
	defer resp.Body.Close()

	switch providerID {
	case catwalk.InferenceProviderZAI:
		if resp.StatusCode == http.StatusUnauthorized {
			return fmt.Errorf("failed to connect to provider %s: %s", c.ID, resp.Status)

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Check the provider's base_url in crushrc/crush.json for typos and ensure it is a valid absolute http(s) URL.
  2. If the URL comes from an env variable, print it (echo $VAR) and fix the value.
  3. Re-copy the endpoint URL from the provider's documentation.
  4. Run the URL through a quick parse check (e.g. `python3 -c "import urllib.parse;urllib.parse.urlparse('...')"`) to confirm validity.

Example fix

// before (crushrc)
provider myprovider
  base_url "https://api.example.com/ v1" // space makes URL unparseable
end
// after
provider myprovider
  base_url "https://api.example.com/v1"
end
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(baseURL)
if err != nil || u.Scheme == "" || u.Host == "" {
    return fmt.Errorf("provider base_url %q is not a valid absolute URL", baseURL)
}

Type guard

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

Try / catch

if err := validateProviderKey(ctx, cfg); err != nil {
    if strings.Contains(err.Error(), "failed to create request") {
        log.Fatalf("fix base_url for %s: %v", cfg.ID, err)
    }
    return err
}

Prevention

When it happens

Trigger: API-key validation against a provider whose resolved test URL (base URL or path in the provider catalog) cannot be parsed by net/url — e.g. a custom base_url in crushrc containing spaces, control characters, or missing scheme artifacts.

Common situations: A hand-edited custom base URL with a typo ("htp://", spaces, trailing braces); an env-resolved base URL that expanded to an empty or malformed string; copy-pasting a URL with invisible characters.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/30bc27b6e4a18b87. Report an issue: GitHub.