{"record":{"id":"790a2b0f9970d291","repo":"Billionmail/BillionMail","slug":"api-key-validation-failed-w","errorCode":null,"errorMessage":"API key validation failed: %w","messagePattern":"API key validation failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/askai/supplier.go","lineNumber":501,"sourceCode":"\tif supplierName == \"\" || baseUrl == \"\" || apiKey == \"\" {\n\t\treturn errors.New(\"supplier name, base URL, and API key are required\")\n\t}\n\n\t// Validate base URL format\n\tparsedUrl, err := url.ParseRequestURI(baseUrl)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid base URL format: %w\", err)\n\t}\n\tif parsedUrl.Scheme != \"http\" && parsedUrl.Scheme != \"https\" {\n\t\treturn errors.New(\"base URL must use http or https protocol\")\n\t}\n\t// Ensure the base URL ends with a slash\n\tif err := testBaseURLAccessibility(baseUrl); err != nil {\n\t\treturn fmt.Errorf(\"base URL accessibility test failed: %w\", err)\n\t}\n\t// Validate API key by making a request to the models endpoint\n\tif err := testAPIKeyValidity(baseUrl, apiKey); err != nil {\n\t\treturn fmt.Errorf(\"API key validation failed: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// testBaseURLAccessibility checks if the base URL is accessible by sending a HEAD request.\n// It returns an error if the request fails or if the response status is not OK (200).\nfunc testBaseURLAccessibility(baseUrl string) error {\n\tclient := &http.Client{Timeout: 3 * time.Second}\n\tresp, err := client.Head(baseUrl)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer resp.Body.Close()\n\treturn nil\n}\n\n// testAPIKeyValidity checks if the provided API key is valid by making a GET request to the models endpoint.","sourceCodeStart":483,"sourceCodeEnd":519,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/askai/supplier.go#L483-L519","documentation":"Testing validates the API key by issuing a GET to the /models endpoint via testAPIKeyValidity. Any failure there (non-200/401/404 status, network error, bad request) is wrapped as 'API key validation failed: %w'. The wrapped cause reveals whether it was auth-related or another HTTP problem.","triggerScenarios":"Calling askai.Testing with an invalid, revoked, or malformed API key; the models endpoint returning an unexpected status (403, 500); network failure during the GET request.","commonSituations":"Copied key missing characters or containing whitespace; key revoked or rotated on the provider side; key valid for a different provider/endpoint than baseUrl points to; provider outage returning 5xx; account lacks access to the models endpoint (403).","solutions":["Inspect the wrapped inner error/status to see the actual response code","Re-copy the API key from the provider dashboard and confirm it matches the chosen baseUrl's provider","Check the account/key status on the provider side (revoked, expired, no credit)","Test the key manually: curl -H 'Authorization: Bearer <key>' <baseUrl>/models","Verify the endpoint path exists for the provider version in use"],"exampleFix":"// before\nerr := askai.Testing(name, url, \"sk-...truncated\") // key malformed\n// after\napiKey := strings.TrimSpace(os.Getenv(\"PROVIDER_API_KEY\"))\nif apiKey == \"\" || len(apiKey) < 20 { return errors.New(\"API key looks invalid\") }\nerr := askai.Testing(name, url, apiKey)","handlingStrategy":"try-catch","validationCode":"func keyLooksPlausible(key string) bool {\n    k := strings.TrimSpace(key)\n    return len(k) >= 20 && !strings.ContainsAny(k, \" \\n\\t\")\n}\nif !keyLooksPlausible(apiKey) { return errors.New(\"API key missing or malformed\") }","typeGuard":null,"tryCatchPattern":"if err := askai.Testing(name, baseUrl, apiKey); err != nil {\n    var detail string\n    if strings.HasPrefix(err.Error(), \"API key validation failed:\") {\n        detail = strings.TrimPrefix(err.Error(), \"API key validation failed: \")\n        return fmt.Errorf(\"check your key at the provider dashboard: %s\", detail)\n    }\n    return err\n}","preventionTips":["Re-copy keys directly from the provider dashboard; avoid manual retyping","Trim whitespace/newlines around stored keys","Ensure the key's provider matches the baseUrl's provider","Check account status (active, funded, not revoked) before testing"],"tags":["go","api-key","authentication","http","supplier"],"backgroundTag":"api-key-validation-failed","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}