cli/cli · error

api call failed

Error message

api call failed

What it means

Generic non-2xx indicator in the garden command's HTTP helper (used for the commits/contributions animation data). After client.Do succeeds at the transport level, any status code outside 200-299 (other than the special-cased 204) collapses into this message with no status code or body attached, which is why it is unhelpfully vague.

Source

Thrown at pkg/cmd/repo/garden/http.go:98

// getResponse performs the API call and returns the response's link header values.
// If the "Link" header is missing, the returned slice will be nil.
func getResponse(client *http.Client, url safeurl.SafeURL, data interface{}) ([]string, error) {
	req, err := http.NewRequest("GET", url.String(), nil)
	if err != nil {
		return nil, err
	}

	req.Header.Set("Content-Type", "application/json; charset=utf-8")
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	success := resp.StatusCode >= 200 && resp.StatusCode < 300
	if !success {
		return nil, errors.New("api call failed")
	}

	links := resp.Header["Link"]

	if resp.StatusCode == http.StatusNoContent {
		return links, nil
	}

	b, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(b, &data)
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to 0eeec0b92e)

Solutions

  1. Check auth first: gh auth status; refresh if expired
  2. Reproduce the failure with a data-rich command: gh repo view <repo> --json name, or gh api /repos/OWNER/REPO to see the real status and message
  3. Wait and retry if you were rate limited (check remaining quota: gh api rate_limit)
  4. If you are developing against this helper, replace the bare error with api.HandleHTTPError(resp) or fmt.Errorf including resp.StatusCode and the body

Example fix

// before
if !success {
    return nil, errors.New("api call failed")
}
// after
if !success {
    return nil, fmt.Errorf("api call failed: %s", resp.Status)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight the same endpoint with full error reporting:
if _, err := ghapi("GET", "/repos/"+owner+"/"+repo); err != nil {
    return fmt.Errorf("garden prerequisites failed: %w", err)
}

Try / catch

links, err := gardenHTTP(client, url)
if err != nil && err.Error() == "api call failed" {
    // the helper discards status/body; re-check auth and rate limits:
    _ = run("gh", "auth", "status")
    return fmt.Errorf("garden API call failed; check gh auth status and rate limits")
}

Prevention

When it happens

Trigger: The garden GraphQL/REST call returning 401 (bad token), 403 (rate limit/SAML), 404 (repo not found), or 5xx. The response body, which contains the actual reason, is discarded; only the Link header is kept for pagination.

Common situations: Expired gh credentials, hitting a secondary rate limit while the animation polls, private repos invisible to the token, or GitHub incidents. Users see only 'api call failed' and cannot tell which of these it is.

Related errors


AI-assisted analysis of cli/cli@0eeec0b92e (2026-08-15). Data as JSON: /api/errors/36eead2f34098f79. Report an issue: GitHub.