fix(provider): improve error messages for non-JSON API responses
Add multi-layer validation to detect and report HTML error pages from misconfigured API endpoints: 1. Check Content-Type header for application/json 2. Detect HTML content by checking for '<' prefix and doctype 3. Show response preview in JSON parse errors This helps users quickly identify api_base URL configuration issues instead of seeing cryptic 'invalid character < looking for beginning of value' errors. Fixes the case where APIs return HTML error pages (404, rate limit pages, etc.) when the endpoint URL is incorrect.
This commit is contained in:
parent
2f4f45080b
commit
fe7ffa8af7
1 changed files with 27 additions and 1 deletions
|
|
@ -192,10 +192,31 @@ func (p *Provider) Chat(
|
||||||
return nil, fmt.Errorf("API request failed:\n Status: %d\n Body: %s", resp.StatusCode, string(body))
|
return nil, fmt.Errorf("API request failed:\n Status: %d\n Body: %s", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check Content-Type header to catch HTML error pages early
|
||||||
|
contentType := resp.Header.Get("Content-Type")
|
||||||
|
if contentType != "" && !strings.Contains(strings.ToLower(contentType), "application/json") {
|
||||||
|
// Truncate body for error message
|
||||||
|
preview := string(body)
|
||||||
|
if len(preview) > 200 {
|
||||||
|
preview = preview[:200] + "..."
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("API returned non-JSON response (Content-Type: %s, check api_base URL): %s", contentType, preview)
|
||||||
|
}
|
||||||
|
|
||||||
return parseResponse(body)
|
return parseResponse(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseResponse(body []byte) (*LLMResponse, error) {
|
func parseResponse(body []byte) (*LLMResponse, error) {
|
||||||
|
// Check if response is HTML (common when API URL is wrong or returns error page)
|
||||||
|
if len(body) > 0 && (body[0] == '<' || bytes.HasPrefix(bytes.ToLower(body[:min(len(body), 15)]), []byte("<!doctype")) || bytes.HasPrefix(bytes.ToLower(body[:min(len(body), 6)]), []byte("<html"))) {
|
||||||
|
// Truncate HTML content for error message
|
||||||
|
htmlPreview := string(body)
|
||||||
|
if len(htmlPreview) > 200 {
|
||||||
|
htmlPreview = htmlPreview[:200] + "..."
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("API returned HTML instead of JSON (check api_base URL): response starts with %q", htmlPreview)
|
||||||
|
}
|
||||||
|
|
||||||
var apiResponse struct {
|
var apiResponse struct {
|
||||||
Choices []struct {
|
Choices []struct {
|
||||||
Message struct {
|
Message struct {
|
||||||
|
|
@ -223,7 +244,12 @@ func parseResponse(body []byte) (*LLMResponse, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.Unmarshal(body, &apiResponse); err != nil {
|
if err := json.Unmarshal(body, &apiResponse); err != nil {
|
||||||
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
|
// Provide more context for JSON parse errors
|
||||||
|
preview := string(body)
|
||||||
|
if len(preview) > 100 {
|
||||||
|
preview = preview[:100] + "..."
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("failed to unmarshal response (got: %q): %w", preview, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(apiResponse.Choices) == 0 {
|
if len(apiResponse.Choices) == 0 {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue