Skip to content

Commit f01346d

Browse files
LysandreJiksgugger
andcommitted
Add request ID to all requests (#909)
* Add request ID to all requests * Typo * Typo * Review comments * Update src/huggingface_hub/utils/_errors.py Co-authored-by: Sylvain Gugger <[email protected]> Co-authored-by: Sylvain Gugger <[email protected]>
1 parent f98eeff commit f01346d

File tree

4 files changed

+40
-21
lines changed

4 files changed

+40
-21
lines changed

src/huggingface_hub/commands/lfs.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from huggingface_hub.lfs import LFS_MULTIPART_UPLOAD_COMMAND
3030

3131
from ..utils import logging
32+
from ..utils._errors import _raise_with_request_id
3233

3334

3435
logger = logging.get_logger(__name__)
@@ -212,7 +213,7 @@ def run(self):
212213
filepath, seek_from=i * chunk_size, read_limit=chunk_size
213214
) as data:
214215
r = requests.put(presigned_url, data=data)
215-
r.raise_for_status()
216+
_raise_with_request_id(r)
216217
parts.append(
217218
{
218219
"etag": r.headers.get("etag"),
@@ -238,6 +239,6 @@ def run(self):
238239
"parts": parts,
239240
},
240241
)
241-
r.raise_for_status()
242+
_raise_with_request_id(r)
242243

243244
write_msg({"event": "complete", "oid": oid})

src/huggingface_hub/hf_api.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
SPACES_SDK_TYPES,
3333
)
3434
from .utils import logging
35-
from .utils._errors import _raise_for_status
35+
from .utils._errors import _raise_for_status, _raise_with_request_id
3636
from .utils._fixes import JSONDecodeError
3737
from .utils.endpoint_helpers import (
3838
AttributeDictionary,
@@ -535,7 +535,7 @@ def whoami(self, token: Optional[str] = None) -> Dict:
535535
path = f"{self.endpoint}/api/whoami-v2"
536536
r = requests.get(path, headers={"authorization": f"Bearer {token}"})
537537
try:
538-
r.raise_for_status()
538+
_raise_with_request_id(r)
539539
except HTTPError as e:
540540
raise HTTPError(
541541
"Invalid user token. If you didn't pass a user token, make sure you "
@@ -629,7 +629,7 @@ def get_model_tags(self) -> ModelTags:
629629
"Gets all valid model tags as a nested namespace object"
630630
path = f"{self.endpoint}/api/models-tags-by-type"
631631
r = requests.get(path)
632-
r.raise_for_status()
632+
_raise_with_request_id(r)
633633
d = r.json()
634634
return ModelTags(d)
635635

@@ -639,7 +639,7 @@ def get_dataset_tags(self) -> DatasetTags:
639639
"""
640640
path = f"{self.endpoint}/api/datasets-tags-by-type"
641641
r = requests.get(path)
642-
r.raise_for_status()
642+
_raise_with_request_id(r)
643643
d = r.json()
644644
return DatasetTags(d)
645645

@@ -778,7 +778,7 @@ def list_models(
778778
if cardData is not None:
779779
params.update({"cardData": cardData})
780780
r = requests.get(path, params=params, headers=headers)
781-
r.raise_for_status()
781+
_raise_with_request_id(r)
782782
d = r.json()
783783
res = [ModelInfo(**x) for x in d]
784784
if emissions_thresholds is not None:
@@ -971,7 +971,7 @@ def list_datasets(
971971
if cardData:
972972
params.update({"full": True})
973973
r = requests.get(path, params=params, headers=headers)
974-
r.raise_for_status()
974+
_raise_with_request_id(r)
975975
d = r.json()
976976
return [DatasetInfo(**x) for x in d]
977977

@@ -1026,7 +1026,7 @@ def list_metrics(self) -> List[MetricInfo]:
10261026
path = f"{self.endpoint}/api/metrics"
10271027
params = {}
10281028
r = requests.get(path, params=params)
1029-
r.raise_for_status()
1029+
_raise_with_request_id(r)
10301030
d = r.json()
10311031
return [MetricInfo(**x) for x in d]
10321032

@@ -1405,7 +1405,7 @@ def create_repo(
14051405
)
14061406

14071407
try:
1408-
r.raise_for_status()
1408+
_raise_with_request_id(r)
14091409
except HTTPError as err:
14101410
if not (exist_ok and err.response.status_code == 409):
14111411
try:

src/huggingface_hub/utils/_errors.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,27 +52,44 @@ def _raise_for_status(request):
5252
Internal version of `request.raise_for_status()` that will refine a
5353
potential HTTPError.
5454
"""
55+
request_id = request.headers.get("X-Request-Id")
56+
5557
if "X-Error-Code" in request.headers:
5658
error_code = request.headers["X-Error-Code"]
5759
if error_code == "RepoNotFound":
5860
raise RepositoryNotFoundError(
59-
f"404 Client Error: Repository Not Found for url: {request.url}. "
60-
"If the repo is private, make sure you are authenticated."
61+
f"404 Client Error: Repository Not Found for url: {request.url}. If the"
62+
" repo is private, make sure you are authenticated. (Request ID:"
63+
f" {request_id})"
6164
)
6265
elif error_code == "RevisionNotFound":
6366
raise RevisionNotFoundError(
64-
f"404 Client Error: Revision Not Found for url: {request.url}"
67+
f"404 Client Error: Revision Not Found for url: {request.url}. (Request"
68+
f" ID: {request_id})"
6569
)
6670
elif error_code == "EntryNotFound":
6771
raise EntryNotFoundError(
68-
f"404 Client Error: Entry Not Found for url: {request.url}"
72+
f"404 Client Error: Entry Not Found for url: {request.url}. (Request"
73+
f" ID: {request_id})"
6974
)
7075

7176
if request.status_code == 401:
7277
# The repo was not found and the user is not Authenticated
7378
raise RepositoryNotFoundError(
74-
f"401 Client Error: Repository Not Found for url: {request.url}. "
75-
"If the repo is private, make sure you are authenticated."
79+
f"401 Client Error: Repository Not Found for url: {request.url}. If the"
80+
" repo is private, make sure you are authenticated. (Request ID:"
81+
f" {request_id})"
7682
)
7783

78-
request.raise_for_status()
84+
_raise_with_request_id(request)
85+
86+
87+
def _raise_with_request_id(request):
88+
request_id = request.headers.get("X-Request-Id")
89+
try:
90+
request.raise_for_status()
91+
except Exception as e:
92+
if request_id is not None and len(e.args) > 0 and isinstance(e.args[0], str):
93+
e.args = (e.args[0] + f" (Request ID: {request_id})",) + e.args[1:]
94+
95+
raise e

tests/test_hf_api.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,9 @@ def test_whoami(self):
197197
@retry_endpoint
198198
def test_delete_repo_error_message(self):
199199
# test for #751
200-
with pytest.raises(
201-
HTTPError,
202-
match="404 Client Error: Repository Not Found",
200+
with self.assertRaisesRegex(
201+
requests.exceptions.HTTPError,
202+
r"404 Client Error: Repository Not Found (.+) \(Request ID: .+\)",
203203
):
204204
self._api.delete_repo("repo-that-does-not-exist", token=self._token)
205205

@@ -970,7 +970,8 @@ def test_model_info(self):
970970
shutil.rmtree(os.path.dirname(HfFolder.path_token))
971971
# Test we cannot access model info without a token
972972
with self.assertRaisesRegex(
973-
requests.exceptions.HTTPError, "401 Client Error: Repository Not Found"
973+
requests.exceptions.HTTPError,
974+
r"401 Client Error: Repository Not Found for url: (.+) \(Request ID: .+\)",
974975
):
975976
_ = self._api.model_info(repo_id=f"{USER}/{self.REPO_NAME}")
976977
# Test we can access model info with a token

0 commit comments

Comments
 (0)