router-for-me/CLIProxyAPI · error

response JSON does not contain models array

Error message

response JSON does not contain models array

What it means

After successfully parsing the response JSON, countModels requires a top-level `models` array. If the decoded object has no `models` key at all (payload.Models == nil), it returns `response JSON does not contain models array`. The check is intentionally loose (per the code comment): this tool dumps the upstream payload, and strict catalog validation belongs to cmd/validate_codex_models — but a payload without any models array is unusable even for dumping.

Source

Thrown at cmd/fetch_codex_models/main.go:308

		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
}

func metaStringValue(m map[string]any, key string) string {
	if m == nil {
		return ""
	}
	v, ok := m[key]

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Dump the top-level keys of the returned JSON to see what the endpoint actually sent instead of models.
  2. Update the Codex client version used for the request; endpoint shape follows client generation.
  3. If a gateway rewrites responses, exclude the Codex models URL from rewriting.
  4. Run cmd/validate_codex_models against known-good data to confirm which side changed.
Defensive patterns

Strategy: validation

Validate before calling

func hasModelsArray(b []byte) bool {
    return gjson.GetBytes(b, "models").IsArray()
}

Type guard

func isMissingModelsArray(err error) bool {
    return err != nil && strings.Contains(err.Error(), "does not contain models array")
}

Prevention

When it happens

Trigger: The 2xx JSON response is a valid object but lacks `models`: an error envelope like {"error": ...} returned with 200, an auth redirect payload, an upstream API revision that renamed/removed the field, or a different endpoint answering than expected.

Common situations: Endpoint contract change after Codex client update; gateways that wrap responses in {"data": ...}; tokens that entitle to a different response shape; stale cached responses from a proxy.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/29c9697fdb8fe497. Report an issue: GitHub.