jira
jira copied to clipboard
KeyError: X-RateLimit-FillRate
Bug summary
https://github.com/pycontribs/jira/blob/main/jira/resilientsession.py#L287 As far as i can tell, JIRA cloud does not set this response header when rate limiting. The only rate limiting headers i can see are: X-Ratelimit-Limit. X-Ratelimit-Remaining, X-Ratelimit-Reset and Retry-After.
Is there an existing issue for this?
- [X] I have searched the existing issues
Jira Instance type
Jira Cloud (Hosted by Atlassian)
Jira instance version
No response
jira-python version
3.3.2
Python Interpreter version
3.9
Which operating systems have you used?
- [ ] Linux
- [ ] macOS
- [X] Windows
Reproduction steps
# 1. Given a Jira client instance
jira: JIRA
# 2. When I call the function with argument x
jira.the_function(x)
# 3.
...
Stack trace
KeyError: X-RateLimit-FillRate
Expected behaviour
No KeyError and request is retried after 'retry-after' amount.
Additional Context
No response
Thanks for creating this issue. Is there any timeline for when a fix will be out for this?
Also, perhaps its worth noting that this was introduced in 3.3.0 not 3.3.2 -
https://github.com/pycontribs/jira/compare/3.2.0...3.3.0#diff-0605333df4b31ca7f97b2591e3bcba9c71ea201f4a88e383316e7f6c1c478e06R286
Encountering this problem as well. Here's a little more for a stack trace.
File "...\mycode", line 123, in my_function
self.jira.my_function(
File "...\AppData\Roaming\Python\Python39\site-packages\jira-3.4.1-py3.9.egg\jira\client.py", line 119, in wrapper
result = func(*arg_list, **kwargs)
File "...\AppData\Roaming\Python\Python39\site-packages\jira-3.4.1-py3.9.egg\jira\client.py", line 2497, in create_issue_link
return self._session.post(url, data=json.dumps(data))
File "...\appdata\local\programs\python\python39\lib\site-packages\requests\sessions.py", line 590, in post
return self.request('POST', url, data=data, json=json, **kwargs)
File "...\AppData\Roaming\Python\Python39\site-packages\jira-3.4.1-py3.9.egg\jira\resilientsession.py", line 213, in request
if is_allowed_to_retry() and self.__recoverable(
File "...\AppData\Roaming\Python\Python39\site-packages\jira-3.4.1-py3.9.egg\jira\resilientsession.py", line 286, in __recoverable
number_of_tokens_issued_per_interval = response.headers[
File "...\appdata\local\programs\python\python39\lib\site-packages\requests\structures.py", line 54, in __getitem__
return self._store[key.lower()][1]
KeyError: 'x-ratelimit-fillrate'
In my case the only headers to go with 429 error are:
{
"content-length": "117",
"cache-control": "no-cache",
"content-type": "text/html"
}
The rest of the timeout logic works fine if I remove headers access. The only thing is this headers KeyError.
In case it's helpful, I got this error and rich
gave me this traceback, which includes the headers:
│ C:\Users\edp\AppData\Local\pypoetry\Cache\virtualenvs\trac-to-jira-ZN2GFehq-py3.10\lib\site-pack │
│ ages\requests\sessions.py:635 in post │
│ │
│ 632 │ │ :rtype: requests.Response │
│ 633 │ │ """ │
│ 634 │ │ │
│ ❱ 635 │ │ return self.request("POST", url, data=data, json=json, **kwargs) │
│ 636 │ │
│ 637 │ def put(self, url, data=None, **kwargs): │
│ 638 │ │ r"""Sends a PUT request. Returns :class:`Response` object. │
│ │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ data = '{"body": "xxx │ │
│ │ xxx │ │
│ │ json = None │ │
│ │ kwargs = {} │ │
│ │ self = <jira.resilientsession.ResilientSession object at 0x000001CFADEEA1D0> │ │
│ │ url = 'https://mydomain.atlassian.net/rest/api/2/issue/PM-809/comment' │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ C:\Users\edp\AppData\Local\pypoetry\Cache\virtualenvs\trac-to-jira-ZN2GFehq-py3.10\lib\site-pack │
│ ages\jira\resilientsession.py:213 in request │
│ │
│ 210 │ │ │ # Decide if we should keep retrying │
│ 211 │ │ │ response_or_exception = response if response is not None else exception │
│ 212 │ │ │ retry_number += 1 │
│ ❱ 213 │ │ │ if is_allowed_to_retry() and self.__recoverable( │
│ 214 │ │ │ │ response_or_exception, url, method.upper(), retry_number │
│ 215 │ │ │ ): │
│ 216 │ │ │ │ _prepare_retry_class.prepare(processed_kwargs) # type: ignore[arg-type] │
│ │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ __class__ = <class 'jira.resilientsession.ResilientSession'> │ │
│ │ _prepare_retry_class = <jira.resilientsession.PassthroughRetryPrepare object at │ │
│ │ 0x000001CFAC1F6380> │ │
│ │ exception = None │ │
│ │ is_allowed_to_retry = <function ResilientSession.request.<locals>.is_allowed_to_retry at │ │
│ │ 0x000001CFAF832290> │ │
│ │ kwargs = { │ │
│ │ │ 'data': '{"body": "xxx, │ │
│ │ │ 'json': None │ │
│ │ } │ │
│ │ method = 'POST' │ │
│ │ processed_kwargs = { │ │
│ │ │ 'data': '{"body": "{0, │ │
│ │ │ 'json': None, │ │
│ │ │ 'headers': {'User-Agent': 'python-requests/2.28.1', │ │
│ │ 'Accept-Encoding': 'gzip, deflate', 'Accept': │ │
│ │ 'application/json,*.*;q=0.9', 'Connection': 'keep-alive', │ │
│ │ 'Cache-Control': 'no-cache', 'Content-Type': 'application/json', │ │
│ │ 'X-Atlassian-Token': 'no-check'} │ │
│ │ } │ │
│ │ response = <Response [429]> │ │
│ │ response_or_exception = <Response [429]> │ │
│ │ retry_number = 1 │ │
│ │ self = <jira.resilientsession.ResilientSession object at │ │
│ │ 0x000001CFADEEA1D0> │ │
│ │ url = 'https://mydomain.atlassian.net/rest/api/2/issue/PM-809/comment' │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
C:\Users\edp\AppData\Local\pypoetry\Cache\virtualenvs\trac-to-jira-ZN2GFehq-py3.10\lib\site-pack │
│ ages\jira\resilientsession.py:286 in __recoverable │
│ │
│ 283 │ │ if isinstance(response, Response): │
│ 284 │ │ │ if response.status_code in [429]: │
│ 285 │ │ │ │ is_recoverable = True │
│ ❱ 286 │ │ │ │ number_of_tokens_issued_per_interval = response.headers[ │
│ 287 │ │ │ │ │ "X-RateLimit-FillRate" │
│ 288 │ │ │ │ ] │
│ 289 │ │ │ │ token_issuing_rate_interval_seconds = response.headers[ │
│ │
│ ╭──────────────────────────────────────── locals ────────────────────────────────────────╮ │
│ │ counter = 1 │ │
│ │ is_recoverable = True │ │
│ │ msg = '<Response [429]>' │ │
│ │ request_method = 'POST' │ │
│ │ response = <Response [429]> │ │
│ │ self = <jira.resilientsession.ResilientSession object at 0x000001CFADEEA1D0> │ │
│ │ url = 'https://mydomain.atlassian.net/rest/api/2/issue/PM-809/comment' │ │
│ ╰────────────────────────────────────────────────────────────────────────────────────────╯ │
│ │
│ C:\Users\edp\AppData\Local\pypoetry\Cache\virtualenvs\trac-to-jira-ZN2GFehq-py3.10\lib\site-pack │
│ ages\requests\structures.py:52 in __getitem__ │
│ │
│ 49 │ │ self._store[key.lower()] = (key, value) │
│ 50 │ │
│ 51 │ def __getitem__(self, key): │
│ ❱ 52 │ │ return self._store[key.lower()][1] │
│ 53 │ │
│ 54 │ def __delitem__(self, key): │
│ 55 │ │ del self._store[key.lower()] │
│ │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ key = 'X-RateLimit-FillRate' │ │
│ │ self = {'Date': 'Fri, 03 Mar 2023 17:16:58 GMT', 'Content-Type': │ │
│ │ 'application/json;charset=UTF-8', 'Server': 'AtlassianEdge', 'Timing-Allow-Origin': │ │
│ │ '*', 'X-Arequestid': '72d13a2f5f541fb91d7f7c41eca8c502', 'X-Aaccountid': │ │
│ │ '633371672eaaa5dcfa14bdf8', 'Cache-Control': 'no-cache, no-store, no-transform', │ │
│ │ 'Expect-Ct': │ │
│ │ 'report-uri="https://web-security-reports.services.atlassian.com/expect-ct-report/at… │ │
│ │ max-age=86400', 'X-Content-Type-Options': 'nosniff', 'X-Xss-Protection': '1; │ │
│ │ mode=block', 'Atl-Traceid': '87b7ede713a91672', 'Report-To': '{"endpoints": [{"url": │ │
│ │ "https://dz8aopenkvv6s.cloudfront.net"}], "group": "endpoint-1", │ │
│ │ "include_subdomains": true, "max_age": 600}', 'Nel': '{"failure_fraction": 0.001, │ │
│ │ "include_subdomains": true, "max_age": 600, "report_to": "endpoint-1"}', │ │
│ │ 'Strict-Transport-Security': 'max-age=63072000; includeSubDomains; preload', │ │
│ │ 'Transfer-Encoding': 'chunked'} │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
KeyError: 'x-ratelimit-fillrate'
Hopefully in a release later this weekend