Billionmail/BillionMail · error
unexpected API response: %d %s
Error message
unexpected API response: %d %s
What it means
When the models endpoint responds with any status other than 200, 401, or 404, testAPIKeyValidity fails with 'unexpected API response: <code> <text>'. Notably, 404 is treated as success (some providers don't expose /models), so this error fires for statuses like 403, 429, 500, 502, 503.
Source
Thrown at core/internal/service/askai/supplier.go:547
}
req.Header.Set("Authorization", "Bearer "+apiKey)
req.Header.Set("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
switch resp.StatusCode {
case http.StatusOK:
return nil // API key is successfully validated
case http.StatusUnauthorized:
return errors.New("invalid API key")
case http.StatusNotFound:
return nil
default:
return fmt.Errorf("unexpected API response: %d %s",
resp.StatusCode, http.StatusText(resp.StatusCode))
}
}
// GetSupplierConfig retrieves the configuration for a specific supplier by its name.
// It reads the configuration file and returns a Supplier struct containing the supplier's details.
// If the configuration file does not exist or an error occurs, it returns an error.
func GetSupplierConfig(supplierName string) (*Supplier, error) {
return ReadSupplierConfig(supplierName)
}
// SetSupplierStatus updates the status of a supplier in its configuration file.
// It reads the existing configuration, modifies the status, and saves it back to the file.
func SetSupplierStatus(supplierName string, status bool) error {
supplierConfig, err := ReadSupplierConfig(supplierName)
if err != nil {
return errors.New("supplier configuration not found")
}View on GitHub (pinned to fc36c76c05)
Solutions
- Read the status code in the message and act on it specifically (403 → permissions, 429 → backoff, 5xx → retry later)
- Check the provider's status page for outages
- Verify account permissions to access the models endpoint
- Wait and retry with backoff if rate-limited
- Confirm the baseUrl points to the correct API gateway, not a proxy that masks errors
Example fix
// before
err := askai.Testing(name, url, key) // hit 429 in a retry loop
// after
for i := 0; i < 3; i++ {
err = askai.Testing(name, url, key)
if err == nil || !strings.Contains(err.Error(), "429") { break }
time.Sleep(time.Duration(1<<i) * time.Second)
} Defensive patterns
Strategy: retry
Try / catch
var err error
for attempt := 0; attempt < 3; attempt++ {
err = askai.Testing(name, baseUrl, apiKey)
if err == nil || !strings.Contains(err.Error(), "unexpected API response") { break }
time.Sleep(time.Duration(1<<attempt) * time.Second)
}
if err != nil {
return fmt.Errorf("provider returned an unexpected status; check provider status page: %w", err)
} Prevention
- Check the provider status page before diagnosing as a local problem
- Avoid tight test loops that trigger 429 rate limits
- Verify account permissions if the message shows 403
- Monitor gateway/proxy health if 5xx statuses recur
When it happens
Trigger: GET <baseUrl>/models returns 403 (forbidden), 429 (rate limited), 5xx (server error), or a gateway error while Testing runs.
Common situations: Provider outage or maintenance (5xx); key valid but lacking model-list permission (403); rate limiting during automated test loops (429); reverse proxy returning 502/503; endpoint behind an auth gateway with different error semantics.
Related errors
- base URL accessibility test failed: %w
- API key validation failed: %w
- base URL not configured
- request context is nil
- supplier configuration not found
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/c5e79ea82e08d556.
Report an issue: GitHub.