{"record":{"id":"36eead2f34098f79","repo":"cli/cli","slug":"api-call-failed","errorCode":null,"errorMessage":"api call failed","messagePattern":"api call failed","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/cmd/repo/garden/http.go","lineNumber":98,"sourceCode":"\n// getResponse performs the API call and returns the response's link header values.\n// If the \"Link\" header is missing, the returned slice will be nil.\nfunc getResponse(client *http.Client, url safeurl.SafeURL, data interface{}) ([]string, error) {\n\treq, err := http.NewRequest(\"GET\", url.String(), nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treq.Header.Set(\"Content-Type\", \"application/json; charset=utf-8\")\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer resp.Body.Close()\n\n\tsuccess := resp.StatusCode >= 200 && resp.StatusCode < 300\n\tif !success {\n\t\treturn nil, errors.New(\"api call failed\")\n\t}\n\n\tlinks := resp.Header[\"Link\"]\n\n\tif resp.StatusCode == http.StatusNoContent {\n\t\treturn links, nil\n\t}\n\n\tb, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\terr = json.Unmarshal(b, &data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/cli/cli/blob/0eeec0b92edbe70199f9768522f831d3534f41ad/pkg/cmd/repo/garden/http.go#L80-L116","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check auth first: gh auth status; refresh if expired","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","Wait and retry if you were rate limited (check remaining quota: gh api rate_limit)","If you are developing against this helper, replace the bare error with api.HandleHTTPError(resp) or fmt.Errorf including resp.StatusCode and the body"],"exampleFix":"// before\nif !success {\n    return nil, errors.New(\"api call failed\")\n}\n// after\nif !success {\n    return nil, fmt.Errorf(\"api call failed: %s\", resp.Status)\n}","handlingStrategy":"try-catch","validationCode":"// Pre-flight the same endpoint with full error reporting:\nif _, err := ghapi(\"GET\", \"/repos/\"+owner+\"/\"+repo); err != nil {\n    return fmt.Errorf(\"garden prerequisites failed: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"links, err := gardenHTTP(client, url)\nif err != nil && err.Error() == \"api call failed\" {\n    // the helper discards status/body; re-check auth and rate limits:\n    _ = run(\"gh\", \"auth\", \"status\")\n    return fmt.Errorf(\"garden API call failed; check gh auth status and rate limits\")\n}","preventionTips":["Keep credentials fresh: gh auth status before novelty/interactive commands","If you maintain code calling this helper, include resp.StatusCode in the error","Watch rate limits (gh api rate_limit) when the animation polls repeatedly"],"tags":["garden","http","error-visibility","rate-limit","authentication"],"backgroundTag":null,"analyzedSha":"0eeec0b92edbe70199f9768522f831d3534f41ad","analyzedAt":"2026-08-15T12:31:05.478Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}