chenhg5/cc-connect · error

parse JSON from %s: %w

Error message

parse JSON from %s: %w

What it means

fetchSkillPresetsFromURL wraps json.Unmarshal failures of the downloaded body with "parse JSON from %s: %w". The HTTP layer fully succeeded, but the payload is not valid JSON or does not fit SkillPresetsResponse. This indicates a broken or wrong content source rather than a network problem.

Source

Thrown at core/skill_presets.go:138

	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 SkillPresetsResponse
	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

  1. Save the body (curl the URL) and validate it: jq . body.json — fix the URL to point at the actual JSON file
  2. Verify the response schema still matches SkillPresetsResponse; update the struct or pin a compatible presets version
  3. Ensure the URL serves raw JSON (e.g. raw.githubusercontent.com) not an HTML page
  4. Check Content-Type; some hosts return HTML interstitials to unknown User-Agents

Example fix

// before
url = "https://github.com/org/skills-presets"            // HTML page
// after
url = "https://raw.githubusercontent.com/org/skills-presets/main/presets.json"
Defensive patterns

Strategy: validation

Validate before calling

resp, err := http.Get(sourceURL)
if err == nil {
    ct := resp.Header.Get("Content-Type")
    b, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
    if !strings.Contains(ct, "json") || !json.Valid(b) {
        return fmt.Errorf("%s does not serve valid JSON (content-type %s)", sourceURL, ct)
    }
    var probe SkillPresetsResponse
    if err := json.Unmarshal(b, &probe); err != nil {
        return fmt.Errorf("schema mismatch for %s: %w", sourceURL, err)
    }
}

Type guard

func servesJSON(url string) bool {
    resp, err := http.Get(url)
    if err != nil { return false }
    defer resp.Body.Close()
    b, err := io.ReadAll(io.LimitReader(resp.Body, 4096))
    return err == nil && json.Valid(b)
}

Try / catch

presets, err := fetchSkillPresetsFromURL(url, timeout)
if err != nil {
    if strings.HasPrefix(err.Error(), "parse JSON from") {
        slog.Error("presets source returned invalid JSON; check URL points at raw JSON file", "url", url, "err", err)
    }
    return err
}

Prevention

When it happens

Trigger: A source URL serving HTML (error/redirect page), an empty body, truncated JSON from an interrupted transfer, or a JSON schema that no longer matches SkillPresetsResponse during fetch.

Common situations: URL pointing at a human-readable docs page instead of the raw JSON file; GitHub URL not switched to raw.githubusercontent.com; upstream renamed fields after a schema version bump.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/1873cc4af2a99719. Report an issue: GitHub.