router-for-me/CLIProxyAPI · error
failed to parse response JSON: %w
Error message
failed to parse response JSON: %w
What it means
countModels in cmd/fetch_codex_models/main.go unmarshals the fetched models payload into `{Models []json.RawMessage}`. If the body is not valid JSON (or not a JSON object), json.Unmarshal fails and the error wraps as `failed to parse response JSON: %w`. This means the endpoint answered 2xx but the body is not the expected JSON document — typically an HTML error page, empty body, or a proxy interception.
Source
Thrown at cmd/fetch_codex_models/main.go:302
func codexModelsURL(clientVersion string) (string, error) {
u, err := url.Parse(codexModelsBaseURL + codexModelsPath)
if err != nil {
return "", err
}
if strings.TrimSpace(clientVersion) != "" {
q := u.Query()
q.Set("client_version", strings.TrimSpace(clientVersion))
u.RawQuery = q.Encode()
}
return u.String(), nil
}
func countModels(raw []byte) (int, error) {
var payload struct {
Models []json.RawMessage `json:"models"`
}
if err := json.Unmarshal(raw, &payload); err != nil {
return 0, fmt.Errorf("failed to parse response JSON: %w", err)
}
// Keep this check intentionally loose: fetch_codex_models dumps the upstream
// Codex API payload. Strict CPA catalog validation belongs in
// cmd/validate_codex_models and registry.ValidateCodexClientModelsJSON.
if payload.Models == nil {
return 0, fmt.Errorf("response JSON does not contain models array")
}
return len(payload.Models), nil
}
func prettyJSON(raw []byte) ([]byte, error) {
var buf bytes.Buffer
if err := json.Indent(&buf, raw, "", " "); err != nil {
return nil, err
}
buf.WriteByte('\n')
return buf.Bytes(), nil
}View on GitHub (pinned to 78f0c4079e)
Solutions
- Capture the raw body (curl the same models URL with the same token) and inspect what was actually returned.
- Bypass or configure the intercepting proxy; ensure no HTML block page is served for chatgpt.com backend endpoints.
- Retry once — truncated bodies from connection cuts are transient.
- If the shape genuinely changed upstream, update cmd/fetch_codex_models parsing and check CLIProxyAPI updates.
Defensive patterns
Strategy: type-guard
Validate before calling
// Pre-validate that the fetched body is JSON before counting
func isJSONBody(b []byte) bool {
var v any
return json.Unmarshal(b, &v) == nil
} Type guard
func isJSONParseFailure(err error) bool {
return err != nil && strings.Contains(err.Error(), "failed to parse response JSON")
} Try / catch
if isJSONParseFailure(err) {
// inspect/save the raw body; likely an HTML block page from an intercepting proxy
logBodyForDiagnosis(raw)
} Prevention
- Sanity-check that the response body starts with '{' before parsing.
- Exclude Codex endpoints from corporate proxy interception.
- Retry once on truncated bodies caused by connection cuts.
When it happens
Trigger: 2xx response containing HTML (captive portal, corporate proxy block page, Cloudflare interstitial); empty or truncated body due to connection cut mid-transfer; wrong URL composition; response shape changed to a non-object JSON scalar.
Common situations: Running the fetch tool behind corporate proxies that inject HTML; CDN/WAF challenges; a truncated response from an unstable network; upstream A/B changes to the endpoint.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to parse token response: %w
- failed to parse refresh response: %w
- response JSON does not contain models array
- invalid auth file: %w
- invalid auth file: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/4d76f8d0cb96db86.
Report an issue: GitHub.