charmbracelet/glow · error
unable to parse json: %w
Error message
unable to parse json: %w
What it means
The API body is unmarshalled with json.Unmarshal into a small struct with only download_url. This error means the bytes received were not valid JSON — glow does not check Content-Type or status before parsing, so any non-JSON 200-class or error page that reaches this point fails here. Note the status check happens after parsing, so even a 404 JSON body would parse fine and only fail later.
Source
Thrown at github.go:40
}
apiURL := fmt.Sprintf("https://api.%s/repos/%s/%s/readme", u.Hostname(), owner, repo)
//nolint:bodyclose
// it is closed on the caller
res, err := http.Get(apiURL) //nolint: gosec,noctx
if err != nil {
return nil, fmt.Errorf("unable to get url: %w", err)
}
body, err := io.ReadAll(res.Body)
if err != nil {
return nil, fmt.Errorf("unable to read http response body: %w", err)
}
var result readme
if err := json.Unmarshal(body, &result); err != nil {
return nil, fmt.Errorf("unable to parse json: %w", err)
}
if res.StatusCode == http.StatusOK {
//nolint:bodyclose
// it is closed on the caller
resp, err := http.Get(result.DownloadURL) //nolint: noctx
if err != nil {
return nil, fmt.Errorf("unable to get url: %w", err)
}
if resp.StatusCode == http.StatusOK {
return &source{resp.Body, result.DownloadURL}, nil
}
}
return nil, errors.New("can't find README in GitHub repository")
}
View on GitHub (pinned to e3970c813d)
Solutions
- Inspect what is actually returned: curl -s https://api.github.com/repos/OWNER/REPO/readme | head -c 200
- Remove/fix hosts-file or DNS overrides for api.github.com
- Accept the network's portal/proxy terms or route around the interception
- Use the raw.githubusercontent.com URL directly to sidestep the API response
Example fix
# before (hosts file maps api.github.com to a local stub serving HTML) glow https://github.com/owner/repo # Error: unable to parse json: invalid character '<' looking for beginning of value # after $ sudo sed -i '/api\.github\.com/d' /etc/hosts && glow https://github.com/owner/repo
Defensive patterns
Strategy: try-catch
Validate before calling
// sniff the body before JSON parsing: only parse responses that look like JSON
if len(body) == 0 || (body[0] != '{' && body[0] != '[') {
return nil, fmt.Errorf("non-JSON response (first bytes: %.40q) — captive portal or proxy interception?", string(body))
} Try / catch
var result readme
if err := json.Unmarshal(body, &result); err != nil {
var synErr *json.SyntaxError
if errors.As(err, &synErr) {
// capture evidence for diagnosis instead of a bare 'parse' failure
snippet := string(body)
if len(snippet) > 120 {
snippet = snippet[:120]
}
return nil, fmt.Errorf("unable to parse json at offset %d (body starts with: %s): %w", synErr.Offset, snippet, err)
}
var typeErr *json.UnmarshalTypeError
if errors.As(err, &typeErr) {
return nil, fmt.Errorf("API schema changed: field %s: %w", typeErr.Field, err)
}
return nil, fmt.Errorf("unable to parse json: %w", err)
} Prevention
- Check Content-Type and the first byte of the body before unmarshalling — '<' almost always means an HTML interception page
- Keep hosts-file/DNS overrides for api.github.com out of machines that run glow
- Complete captive-portal logins or exempt api.github.com from SSL inspection before automating fetches
When it happens
Trigger: A captive portal or transparent proxy returning an HTML login/interception page; DNS or hosts-file entries sending api.{hostname} to a server that answers 200 with HTML; GitLab/GitHub mirrors or gateways that return plain-text errors; truncated bodies from intermediary truncation that still exit ReadAll cleanly.
Common situations: Hotel/airport Wi-Fi captive portals; corporate SSL-inspection appliances rewriting responses; custom hosts entries like 127.0.0.1 api.github.com during testing; GitHub Enterprise hosts routed into this function whose API prefix differs.
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
- can't find README in GitHub repository
- invalid url: %s
- unable to get url: %w
- unable to parse json: %w
- can't find README in GitLab repository
AI-assisted analysis of charmbracelet/glow@e3970c813d (2026-08-15).
Data as JSON: /api/errors/88b3293d184ceaa0.
Report an issue: GitHub.