📝 Description
When GitHub's API triggers a secondary rate limit, it responds with a 403 Forbidden status code and includes a Retry-After header. According to the HTTP specification and GitHub's API behavior, this header can be formatted in two ways:
- As a non-negative decimal integer indicating the number of seconds to delay (e.g.,
120).
- As an HTTP-date (RFC 7231 format, e.g.,
Wed, 21 Oct 2015 07:28:00 GMT).
Currently, the go-github client fails to parse the Retry-After header when it is returned as an HTTP-date. As a result, the parsed error (typically AbuseRateLimitError or a generic rate limit error) does not expose the correct retry duration to the caller. This makes it impossible for client applications to implement reliable, automatic retry middleware based on the returned error.
🎯 Acceptance Criteria
🛠️ Technical Specifications & Context
- Location of Logic: The response parsing and error handling logic resides in
github/github.go (specifically within the CheckResponse function which inspects HTTP status codes and constructs error types like AbuseRateLimitError).
- Error Definition: Check
github/github.go for the definition of AbuseRateLimitError. It should have a field representing the retry delay (e.g., RetryAfter *time.Duration or similar).
- Parsing Implementation:
- When extracting the
Retry-After header:
- Attempt to parse it as an integer using
strconv.Atoi(). If successful, convert it to a time.Duration (seconds).
- If integer parsing fails, attempt to parse it as an HTTP-date using
net/http's http.ParseTime() or time.Parse(time.RFC1123, ...) / time.RFC1123A.
- If parsed as a timestamp, calculate the duration relative to the current time (
time.Until(parsedTime)) or expose the absolute target time.
Example helper structure:
// In github/github.go (or equivalent error definition file)
type AbuseRateLimitError struct {
Response *http.Response
Message string `json:"message"`
DocumentationURL string `json:"documentation_url"`
RetryAfter *time.Duration // Should represent the parsed duration
}
🧪 Verification & Testing
- Unit Tests: Add test cases in
github/github_test.go (or the corresponding test file for response parsing):
- Test
CheckResponse with a 403 status code and Retry-After: 60. Verify that the returned error contains a retry duration of 60 seconds.
- Test
CheckResponse with a 403 status code and Retry-After: <Future HTTP-Date> (e.g., a date 5 minutes in the future). Verify that the returned error contains a retry duration of approximately 5 minutes.
- Test
CheckResponse with an invalid or missing Retry-After header to ensure no panics occur and a default/nil value is returned.

This repo is using Opire - what does it mean? 👇
💵 Everyone can add rewards for this issue commenting /reward 100 (replace 100 with the amount).
🕵️♂️ If someone starts working on this issue to earn the rewards, they can comment /try to let everyone know!
🙌 And when they open the PR, they can comment /claim #1 either in the PR description or in a PR's comment.
🪙 Also, everyone can tip any user commenting /tip 20 @Tylerx3udv (replace 20 with the amount, and @Tylerx3udv with the user to tip).
📖 If you want to learn more, check out our documentation.
📝 Description
When GitHub's API triggers a secondary rate limit, it responds with a
403 Forbiddenstatus code and includes aRetry-Afterheader. According to the HTTP specification and GitHub's API behavior, this header can be formatted in two ways:120).Wed, 21 Oct 2015 07:28:00 GMT).Currently, the
go-githubclient fails to parse theRetry-Afterheader when it is returned as an HTTP-date. As a result, the parsed error (typicallyAbuseRateLimitErroror a generic rate limit error) does not expose the correct retry duration to the caller. This makes it impossible for client applications to implement reliable, automatic retry middleware based on the returned error.🎯 Acceptance Criteria
Retry-Afterheader when it is formatted as an integer (seconds).Retry-Afterheader when it is formatted as an HTTP-date (RFC 1123 / RFC 7231 format).AbuseRateLimitError.RetryAfteror equivalent) as a helper field (liketime.Durationor*time.Time).niltime) without panicking.🛠️ Technical Specifications & Context
github/github.go(specifically within theCheckResponsefunction which inspects HTTP status codes and constructs error types likeAbuseRateLimitError).github/github.gofor the definition ofAbuseRateLimitError. It should have a field representing the retry delay (e.g.,RetryAfter *time.Durationor similar).Retry-Afterheader:strconv.Atoi(). If successful, convert it to atime.Duration(seconds).net/http'shttp.ParseTime()ortime.Parse(time.RFC1123, ...)/time.RFC1123A.time.Until(parsedTime)) or expose the absolute target time.Example helper structure:
🧪 Verification & Testing
github/github_test.go(or the corresponding test file for response parsing):CheckResponsewith a403status code andRetry-After: 60. Verify that the returned error contains a retry duration of 60 seconds.CheckResponsewith a403status code andRetry-After: <Future HTTP-Date>(e.g., a date 5 minutes in the future). Verify that the returned error contains a retry duration of approximately 5 minutes.CheckResponsewith an invalid or missingRetry-Afterheader to ensure no panics occur and a default/nil value is returned.This repo is using Opire - what does it mean? 👇
💵 Everyone can add rewards for this issue commenting
/reward 100(replace100with the amount).🕵️♂️ If someone starts working on this issue to earn the rewards, they can comment
/tryto let everyone know!🙌 And when they open the PR, they can comment
/claim #1either in the PR description or in a PR's comment.🪙 Also, everyone can tip any user commenting
/tip 20 @Tylerx3udv(replace20with the amount, and@Tylerx3udvwith the user to tip).📖 If you want to learn more, check out our documentation.