/
_errors.py
314 lines (247 loc) · 10.7 KB
/
_errors.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
from typing import Optional
from requests import HTTPError, Response
from ._deprecation import _deprecate_method
from ._fixes import JSONDecodeError
class HfHubHTTPError(HTTPError):
"""
HTTPError to inherit from for any custom HTTP Error raised in HF Hub.
Any HTTPError is converted at least into a `HfHubHTTPError`. If some information is
sent back by the server, it will be added to the error message.
Added details:
- Request id from "X-Request-Id" header if exists.
- Server error message if we can found one in the response body.
Example:
```py
import requests
from huggingface_hub.utils import hf_raise_for_status, HfHubHTTPError
response = requests.post(...)
try:
hf_raise_for_status(response)
except HfHubHTTPError as e:
print(str(e)) # formatted message
e.request_id, e.server_message # details returned by server
# Complete the error message with additional information once it's raised
e.append_to_message("\n`create_commit` expects the repository to exist.")
raise
```
"""
request_id: Optional[str] = None
server_message: Optional[str] = None
def __init__(self, message: str, response: Optional[Response]):
# Parse server information if any.
if response is not None:
self.request_id = response.headers.get("X-Request-Id")
try:
self.server_message = response.json().get("error", None)
except JSONDecodeError:
pass
super().__init__(
_format_error_message(
message,
request_id=self.request_id,
server_message=self.server_message,
),
response=response,
)
def append_to_message(self, additional_message: str) -> None:
"""Append additional information to the `HfHubHTTPError` initial message."""
self.args = (self.args[0] + additional_message,) + self.args[1:]
class RepositoryNotFoundError(HfHubHTTPError):
"""
Raised when trying to access a hf.co URL with an invalid repository name, or
with a private repo name the user does not have access to.
Example:
```py
>>> from huggingface_hub import model_info
>>> model_info("<non_existent_repository>")
(...)
huggingface_hub.utils._errors.RepositoryNotFoundError: 401 Client Error. (Request ID: PvMw_VjBMjVdMz53WKIzP)
Repository Not Found for url: https://huggingface.co/api/models/%3Cnon_existent_repository%3E.
Please make sure you specified the correct `repo_id` and `repo_type`.
If the repo is private, make sure you are authenticated.
Invalid username or password.
```
"""
class RevisionNotFoundError(HfHubHTTPError):
"""
Raised when trying to access a hf.co URL with a valid repository but an invalid
revision.
Example:
```py
>>> from huggingface_hub import hf_hub_download
>>> hf_hub_download('bert-base-cased', 'config.json', revision='<non-existent-revision>')
(...)
huggingface_hub.utils._errors.RevisionNotFoundError: 404 Client Error. (Request ID: Mwhe_c3Kt650GcdKEFomX)
Revision Not Found for url: https://huggingface.co/bert-base-cased/resolve/%3Cnon-existent-revision%3E/config.json.
```
"""
class EntryNotFoundError(HfHubHTTPError):
"""
Raised when trying to access a hf.co URL with a valid repository and revision
but an invalid filename.
Example:
```py
>>> from huggingface_hub import hf_hub_download
>>> hf_hub_download('bert-base-cased', '<non-existent-file>')
(...)
huggingface_hub.utils._errors.EntryNotFoundError: 404 Client Error. (Request ID: 53pNl6M0MxsnG5Sw8JA6x)
Entry Not Found for url: https://huggingface.co/bert-base-cased/resolve/main/%3Cnon-existent-file%3E.
```
"""
class LocalEntryNotFoundError(EntryNotFoundError, FileNotFoundError, ValueError):
"""
Raised when trying to access a file that is not on the disk when network is
disabled or unavailable (connection issue). The entry may exist on the Hub.
Note: `ValueError` type is to ensure backward compatibility.
Note: `LocalEntryNotFoundError` derives from `HTTPError` because of `EntryNotFoundError`
even when it is not a network issue.
Example:
```py
>>> from huggingface_hub import hf_hub_download
>>> hf_hub_download('bert-base-cased', '<non-cached-file>', local_files_only=True)
(...)
huggingface_hub.utils._errors.LocalEntryNotFoundError: Cannot find the requested files in the disk cache and outgoing traffic has been disabled. To enable hf.co look-ups and downloads online, set 'local_files_only' to False.
```
"""
def __init__(self, message: str):
super().__init__(message, response=None)
class BadRequestError(HfHubHTTPError, ValueError):
"""
Raised by `hf_raise_for_status` when the server returns a HTTP 400 error.
Example:
```py
>>> resp = requests.post("hf.co/api/check", ...)
>>> hf_raise_for_status(resp, endpoint_name="check")
huggingface_hub.utils._errors.BadRequestError: Bad request for check endpoint: {details} (Request ID: XXX)
```
"""
def hf_raise_for_status(
response: Response, endpoint_name: Optional[str] = None
) -> None:
"""
Internal version of `response.raise_for_status()` that will refine a
potential HTTPError. Raised exception will be an instance of `HfHubHTTPError`.
This helper is meant to be the unique method to raise_for_status when making a call
to the Hugging Face Hub.
Example:
```py
import requests
from huggingface_hub.utils import hf_raise_for_status, HfHubHTTPError
response = requests.post(...)
try:
hf_raise_for_status(response)
except HfHubHTTPError as e:
print(str(e)) # formatted message
e.request_id, e.server_message # details returned by server
# Complete the error message with additional information once it's raised
e.append_to_message("\n`create_commit` expects the repository to exist.")
raise
```
Args:
response (`Response`):
Response from the server.
endpoint_name (`str`, *optional*):
Name of the endpoint that has been called. If provided, the error message
will be more complete.
<Tip warning={true}>
Raises when the request has failed:
- [`~utils.RepositoryNotFoundError`]
If the repository to download from cannot be found. This may be because it
doesn't exist, because `repo_type` is not set correctly, or because the repo
is `private` and you do not have access.
- [`~utils.RevisionNotFoundError`]
If the repository exists but the revision couldn't be find.
- [`~utils.EntryNotFoundError`]
If the repository exists but the entry (e.g. the requested file) couldn't be
find.
- [`~utils.BadRequestError`]
If request failed with a HTTP 400 BadRequest error.
- [`~utils.HfHubHTTPError`]
If request failed for a reason not listed above.
</Tip>
"""
try:
response.raise_for_status()
except HTTPError as e:
error_code = response.headers.get("X-Error-Code")
if error_code == "RevisionNotFound":
message = (
f"{response.status_code} Client Error."
+ "\n\n"
+ f"Revision Not Found for url: {response.url}."
)
raise RevisionNotFoundError(message, response) from e
elif error_code == "EntryNotFound":
message = (
f"{response.status_code} Client Error."
+ "\n\n"
+ f"Entry Not Found for url: {response.url}."
)
raise EntryNotFoundError(message, response) from e
elif error_code == "RepoNotFound" or response.status_code == 401:
message = (
f"{response.status_code} Client Error."
+ "\n\n"
+ f"Repository Not Found for url: {response.url}."
+ "\nPlease make sure you specified the correct `repo_id` and"
" `repo_type`."
+ "\nIf the repo is private, make sure you are authenticated."
)
raise RepositoryNotFoundError(message, response) from e
elif response.status_code == 400:
message = (
f"\n\nBad request for {endpoint_name} endpoint:"
if endpoint_name is not None
else "\n\nBad request:"
)
raise BadRequestError(message, response=response) from e
# Convert `HTTPError` into a `HfHubHTTPError` to display request information
# as well (request id and/or server error message)
raise HfHubHTTPError(str(HTTPError), response=response) from e
def _raise_for_status(response):
"""Keep alias for now.
Deprecated but without warning since it is used in transformers.
TODO: deprecate this properly after next release (just after v0.10).
See https://github.com/huggingface/huggingface_hub/pull/1019#issuecomment-1233240452
"""
hf_raise_for_status(response)
@_deprecate_method(version="0.13", message="Use `hf_raise_for_status` instead.")
def _raise_with_request_id(response):
"""Keep alias for now."""
hf_raise_for_status(response)
@_deprecate_method(version="0.13", message="Use `hf_raise_for_status` instead.")
def _raise_convert_bad_request(response: Response, endpoint_name: str):
"""
Calls hf_raise_for_status on resp and converts HTTP 400 errors into ValueError.
Keep alias for now.
"""
hf_raise_for_status(response, endpoint_name=endpoint_name)
def _format_error_message(
message: str, request_id: Optional[str], server_message: Optional[str]
) -> str:
"""
Format the `HfHubHTTPError` error message based on initial message and information
returned by the server.
Used when initializing `HfHubHTTPError`.
"""
# Add message from response body
if (
server_message is not None
and len(server_message) > 0
and server_message.lower() not in message.lower()
):
if "\n\n" in message:
message += "\n" + server_message
else:
message += "\n\n" + server_message
# Add Request ID
if request_id is not None and str(request_id).lower() not in message.lower():
request_id_message = f" (Request ID: {request_id})"
if "\n" in message:
newline_index = message.index("\n")
message = (
message[:newline_index] + request_id_message + message[newline_index:]
)
else:
message += request_id_message
return message