chenhg5/cc-connect · error
parse JSON from %s: %w
Error message
parse JSON from %s: %w
What it means
The fetched presets body is not valid JSON for the expected `ProviderPresetsResponse` shape; `json.Unmarshal` failed and the error is wrapped as `parse JSON from <url>: <cause>`. The HTTP layer succeeded but the payload is malformed or structurally incompatible.
Source
Thrown at core/provider_presets.go:155
client := &http.Client{Timeout: timeout}
resp, err := client.Get(url)
if err != nil {
return nil, fmt.Errorf("HTTP GET %s: %w", url, err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("HTTP GET %s: status %d", url, resp.StatusCode)
}
body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return nil, fmt.Errorf("read body from %s: %w", url, err)
}
var result ProviderPresetsResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, fmt.Errorf("parse JSON from %s: %w", url, err)
}
return &result, nil
}
View on GitHub (pinned to 4000b2338a)
Solutions
- curl the URL and validate the body is well-formed JSON (`jq . <response.json>`).
- Point the presets source at the correct raw JSON URL (for GitHub use raw.githubusercontent.com, not the HTML page).
- Check whether the response exceeds 1 MiB and, if so, raise the LimitReader cap or host a smaller file.
- Confirm the upstream JSON still matches the ProviderPresetsResponse field names/types; update either side if the schema drifted.
Example fix
// before
var result ProviderPresetsResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, fmt.Errorf("parse JSON from %s: %w", url, err)
}
// after (surface context about the offending body)
var result ProviderPresetsResponse
if err := json.Unmarshal(body, &result); err != nil {
return nil, fmt.Errorf("parse JSON from %s: %w (first 200 bytes: %q)", url, err, body[:min(200, len(body))])
} Defensive patterns
Strategy: validation
Validate before calling
trimmed := bytes.TrimSpace(body)
if len(trimmed) == 0 || trimmed[0] != '{' { return fmt.Errorf("%s did not return JSON", url) }
if err := json.Valid(trimmed); err != nil { return fmt.Errorf("invalid JSON from %s: %w", url, err) } Try / catch
var result ProviderPresetsResponse
if err := json.Unmarshal(body, &result); err != nil {
slog.Warn("bad presets payload", "url", url, "error", err)
return staleOrDefaultPresets(), nil
} Prevention
- Point sources at raw JSON endpoints, never HTML pages.
- Keep client and server presets schemas in sync (version the payload).
- Log the first bytes of an unparseable body to diagnose HTML-vs-JSON quickly.
- Remember the 1 MiB LimitReader cap when hosting large presets files.
When it happens
Trigger: Calling fetchPresetsFromURL against a URL that returns HTML (error page, login page), an empty body, truncated JSON (e.g. cut off by the 1 MiB LimitReader), or JSON whose fields do not match ProviderPresetsResponse types.
Common situations: URL accidentally points to an HTML page instead of raw JSON; server behind an auth wall returns a login redirect body with 200; presets schema changed upstream while the client expects the old shape; response larger than the 1 MiB cap so the JSON is truncated.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- decode usage response: %w
- parse JSON from %s: %w
- parse existing Agy hooks %s: %w
- marshal Agy permission hook: %w
- marshal Agy hooks overlay: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/a1f583893e06d76f.
Report an issue: GitHub.