{"record":{"id":"30bc27b6e4a18b87","repo":"charmbracelet/crush","slug":"failed-to-create-request-for-provider-s-w","errorCode":null,"errorMessage":"failed to create request for provider %s: %w","messagePattern":"failed to create request for provider (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/config.go","lineNumber":1020,"sourceCode":"\t\tif strings.HasPrefix(apiKey, \"ABSK\") { // Bedrock API keys\n\t\t\treturn nil\n\t\t}\n\t\treturn errors.New(\"not a valid bedrock api key\")\n\tcase catwalk.TypeVercel:\n\t\t// NOTE: Vercel does not validate API keys on the `/models` endpoint.\n\t\tif strings.HasPrefix(apiKey, \"vck_\") { // Vercel API keys\n\t\t\treturn nil\n\t\t}\n\t\treturn errors.New(\"not a valid vercel api key\")\n\t}\n\n\tctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n\tdefer cancel()\n\n\tclient := &http.Client{}\n\treq, err := http.NewRequestWithContext(ctx, \"GET\", testURL, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create request for provider %s: %w\", c.ID, err)\n\t}\n\tfor k, v := range headers {\n\t\treq.Header.Set(k, v)\n\t}\n\tfor k, v := range c.ExtraHeaders {\n\t\treq.Header.Set(k, v)\n\t}\n\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create request for provider %s: %w\", c.ID, err)\n\t}\n\tdefer resp.Body.Close()\n\n\tswitch providerID {\n\tcase catwalk.InferenceProviderZAI:\n\t\tif resp.StatusCode == http.StatusUnauthorized {\n\t\t\treturn fmt.Errorf(\"failed to connect to provider %s: %s\", c.ID, resp.Status)","sourceCodeStart":1002,"sourceCodeEnd":1038,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/config/config.go#L1002-L1038","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the provider's base_url in crushrc/crush.json for typos and ensure it is a valid absolute http(s) URL.","If the URL comes from an env variable, print it (echo $VAR) and fix the value.","Re-copy the endpoint URL from the provider's documentation.","Run the URL through a quick parse check (e.g. `python3 -c \"import urllib.parse;urllib.parse.urlparse('...')\"`) to confirm validity."],"exampleFix":"// before (crushrc)\nprovider myprovider\n  base_url \"https://api.example.com/ v1\" // space makes URL unparseable\nend\n// after\nprovider myprovider\n  base_url \"https://api.example.com/v1\"\nend","handlingStrategy":"validation","validationCode":"u, err := url.Parse(baseURL)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"provider base_url %q is not a valid absolute URL\", baseURL)\n}","typeGuard":"func isValidURL(raw string) bool {\n    u, err := url.Parse(strings.TrimSpace(raw))\n    return err == nil && (u.Scheme == \"http\" || u.Scheme == \"https\") && u.Host != \"\"\n}","tryCatchPattern":"if err := validateProviderKey(ctx, cfg); err != nil {\n    if strings.Contains(err.Error(), \"failed to create request\") {\n        log.Fatalf(\"fix base_url for %s: %v\", cfg.ID, err)\n    }\n    return err\n}","preventionTips":["Validate custom base URLs at config-load time with url.Parse.","Never hand-edit URLs with editors that insert soft hyphens/spaces.","Source endpoint URLs from provider docs or env, not ad-hoc edits."],"tags":["config","http","url","validation"],"backgroundTag":"invalid-url","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}