r-lib / gh

Minimalistic GitHub API client in R
https://gh.r-lib.org
Other
223 stars 52 forks source link

Studying gh errors in v1.4.0, i.e. in the httr2 era #179

Closed jennybc closed 1 year ago

jennybc commented 1 year ago

Update: I solved the mystery, but am leaving this open in case we think there's something to be done here or in httr2. Skip to the end.

I'm going to call gh inside tryCatch() in usethis, so I wanted to refresh my memory of the classes on a gh error.

The errors in the just-released 1.4.0 version puzzle me a bit. They seem to have very different classes than previous gh errors (fewer classes). And, yet if that were actually true, it seems like gh would be failing its own tests. I'm not sure what to make of it :thinking:


With gh v1.3.1

library(gh)
packageVersion("gh")
#> [1] '1.3.1'

gh("/repos/r-lib/usethis/contents/NOPE")
#> Error in `gh_process_response()` at gh/R/gh.R:176:2:
#> ! GitHub API error (404): Not Found
#> ✖ URL not found: <https://api.github.com/repos/r-lib/usethis/contents/NOPE>
#> ℹ Read more at
#>   <https://docs.github.com/rest/reference/repos#get-repository-content>

#> Backtrace:
#>     ▆
#>  1. └─gh::gh("/repos/r-lib/usethis/contents/NOPE")
#>  2.   └─gh:::gh_process_response(raw) at gh/R/gh.R:176:2
#>  3.     └─gh:::gh_error(response) at gh/R/gh_response.R:4:4
#>  4.       └─cli::cli_abort(...) at gh/R/gh_response.R:69:2
#>  5.         └─rlang::abort(...)
rlang::last_error()
#> <error/github_error>
#> Error in `gh_process_response()` at gh/R/gh.R:176:2:
#> ! GitHub API error (404): Not Found
#> ✖ URL not found: <https://api.github.com/repos/r-lib/usethis/contents/NOPE>
#> ℹ Read more at
#>   <https://docs.github.com/rest/reference/repos#get-repository-content>
#> ---
#> Backtrace:
#>  1. gh::gh("/repos/r-lib/usethis/contents/NOPE")
#>  2. gh:::gh_process_response(raw)
#>       at gh/R/gh.R:176:2
#> Run `rlang::last_trace()` to see the full context.

x <- rlang::catch_cnd(gh("/repos/r-lib/usethis/contents/NOPE"))
class(x)
#> [1] "github_error"   "http_error_404" "rlang_error"    "error"         
#> [5] "condition"

tryCatch(
  gh("/repos/r-lib/usethis/contents/NOPE"),
  error = function(cnd) "ERROR"
)
#> [1] "ERROR"

tryCatch(
  gh("/repos/r-lib/usethis/contents/NOPE"),
  github_error = function(cnd) "GITHUB_ERROR"
)
#> [1] "GITHUB_ERROR"

With gh v1.4.0

library(gh)
packageVersion("gh")
#> [1] '1.4.0'

gh("/repos/r-lib/usethis/contents/NOPE")
#> Error in `gh()`:
#> ! GitHub API error (404): Not Found
#> ✖ URL not found: <https://api.github.com/repos/r-lib/usethis/contents/NOPE>
#> ℹ Read more at
#>   <https://docs.github.com/rest/reference/repos#get-repository-content>

#> Backtrace:
#>     ▆
#>  1. └─gh::gh("/repos/r-lib/usethis/contents/NOPE")
#>  2.   └─gh:::gh_make_request(req)
#>  3.     └─gh:::gh_error(resp, error_call = error_call)
#>  4.       └─cli::cli_abort(...)
#>  5.         └─rlang::abort(...)
rlang::last_error()
#> <error/github_error>
#> Error in `gh()`:
#> ! GitHub API error (404): Not Found
#> ✖ URL not found: <https://api.github.com/repos/r-lib/usethis/contents/NOPE>
#> ℹ Read more at
#>   <https://docs.github.com/rest/reference/repos#get-repository-content>
#> ---
#> Backtrace:
#>  1. gh::gh("/repos/r-lib/usethis/contents/NOPE")
#> Run `rlang::last_trace()` to see the full context.

x <- rlang::catch_cnd(gh("/repos/r-lib/usethis/contents/NOPE"))
class(x)
#> [1] "httr2_fetch" "condition"

tryCatch(
  gh("/repos/r-lib/usethis/contents/NOPE"),
  error = function(cnd) "ERROR"
)
#> [1] "ERROR"

tryCatch(
  gh("/repos/r-lib/usethis/contents/NOPE"),
  github_error = function(cnd) "GITHUB_ERROR"
)
#> [1] "GITHUB_ERROR"
jennybc commented 1 year ago

This seems to be a correct, but unexpected, result of me trying to catch the error with rlang::catch_cnd() and this call to rlang::signal() in httr2::req_perform():

https://github.com/r-lib/httr2/blob/2584361c1853e2ecf4d1728f80def74c351b1b59/R/req-perform.R#L115

This "httr2_fetch" condition gets caught, not the HTTP error I'm expecting to catch.

So if I specifically say I want to catch errors, I get what I expect:

library(gh)
packageVersion("gh")
#> [1] '1.4.0'

gh("/repos/r-lib/usethis/contents/NOPE")
#> Error in `gh()`:
#> ! GitHub API error (404): Not Found
#> ✖ URL not found: <https://api.github.com/repos/r-lib/usethis/contents/NOPE>
#> ℹ Read more at
#>   <https://docs.github.com/rest/reference/repos#get-repository-content>

#> Backtrace:
#>     ▆
#>  1. └─gh::gh("/repos/r-lib/usethis/contents/NOPE")
#>  2.   └─gh:::gh_make_request(req)
#>  3.     └─gh:::gh_error(resp, error_call = error_call)
#>  4.       └─cli::cli_abort(...)
#>  5.         └─rlang::abort(...)
rlang::last_error()
#> <error/github_error>
#> Error in `gh()`:
#> ! GitHub API error (404): Not Found
#> ✖ URL not found: <https://api.github.com/repos/r-lib/usethis/contents/NOPE>
#> ℹ Read more at
#>   <https://docs.github.com/rest/reference/repos#get-repository-content>
#> ---
#> Backtrace:
#>  1. gh::gh("/repos/r-lib/usethis/contents/NOPE")
#> Run `rlang::last_trace()` to see the full context.

x <- rlang::catch_cnd(gh("/repos/r-lib/usethis/contents/NOPE"), classes = "error")
class(x)
#> [1] "github_error"   "http_error_404" "rlang_error"    "error"         
#> [5] "condition"

Maybe this has become more of a question about httr2. Or a documentation issue? Or just a lesson learned.