Invalid issue `self` url returned by Issue API in OAuth app

Hello!

This issue started last Friday (01/12/2024), we use this python jira sdk to update issues this way:

issue = JIRA(options={'server': JIRA_URL, 'headers': {'Authorization': f'Bearer {access_token}'}}).issue("<the issue id>")
issue.update(fields={"summary": "new summary"})

This started breaking last week: the issue is properly retrieved, but the update fails with a 404. I tracked down the problem to the issue object having an incorrect value for self in the payload, see the payload returned for the issue during the initial fetch (I replaced our instance UUID with a random one):

{
    "expand": <snip>,
    "id": "619450",
    "self": "https://api.atlassian.com/rest/api/2/issue/619450",
    "key": "<snip>",
    "fields": {
        "parent": {
            "id": "619448",
            "key": "<snip>",
            "self": "https://api.atlassian.com/ex/jira/396b747a-789f-48ec-a637-d0caefeac0ee/rest/api/2/issue/619448",
            "fields": {
                "summary": "A Summary",
                "status": {
                    "self": "https://api.atlassian.com/ex/jira/396b747a-789f-48ec-a637-d0caefeac0ee/rest/api/2/status/10001",
                    "description": "",
                    "iconUrl": "https://api.atlassian.com/ex/jira/396b747a-789f-48ec-a637-d0caefeac0ee/",
                    "name": "Done",
                    "id": "10001",
                    "statusCategory": {
                        "self": "https://api.atlassian.com/ex/jira/396b747a-789f-48ec-a637-d0caefeac0ee/rest/api/2/statuscategory/3",
                        "id": 3,
                        "key": "done",
                        "colorName": "green",
                        "name": "Done"
                    }
                },
<snip>

"self": "https://api.atlassian.com/rest/api/2/issue/619450" should be "self": "https://api.atlassian.com/ex/jira/396b747a-789f-48ec-a637-d0caefeac0ee/rest/api/2/issue/619450"

You can see that the fields and the parent ticket have the correct values for self, but not the ticket we fetched. This causes the update() call to go to the wrong URL and returns a 404. We updated to the latest version of the SDK. The issue persists even if I provide a jira client explicitly to the update method, because it uses its self.self attribute to resolve the URL.

We could work around the issue by calling the endpoint directly instead of using the SDK, but this seems to point to a bug in the implementation of the REST API, at least for OAuth apps maybe.

Let me know if I overlooked something, or if there is a misconfiguration in our instance instead.

Thank you,
Remi

1 Like

Welcome to the Atlassian developer community @RemiCarton,

I was able to reproduce your bug. I’ll have to direct you to developer support to get that logged and routed to the right team. In the meantime, let’s see if we can consider some workarounds.

At first, I was suspicious that your example was the right way to use the SDK. “Surely, you wouldn’t need to do a GET just to turn around and PUT,” I thought. No, you are 100% correct, that’s how the Python Jira library works. If you have any choice in the matter, I would abandon this hand-coded library.

My recommendation would be to use Uplink instead. I prefer this library because it keeps coupling to an absolute minimum: you only “bind” your code to the API endpoints that you need. That keeps you from having to worry that a change in the GET endpoint would affect the PUT.

Another approach that I’ve used is to generate an SDK from the Open API spec using openapi-python-client. You can expect a few generation-time warnings, and the Python linter has a complaint here and there, but it basically works as expected. This is more like the SDK you have, in that it would provide a full type model and code completion. The advantage is the generated SDK is definitionally complete, whereas the hand-coded one in pycontribs is quite limiting. The downside is the high coupling (to everything in the API) and, because the Jira API is so “wide”, the code completion might be noisy (too many options) and slow.

In both cases, the tricky, Jira-specific stuff that aren’t in those general libraries are the base URL construction (like https://api.atlassian.com/ex/jira/396b747a-789f-48ec-a637-d0caefeac0ee), and Atlassian’s sometimes quirky OAuth.

1 Like

Thanks for the quick feedback! I recently picked up this code from a legacy service since alerts started firing because of this issue.

I agree with you, as I was digging in this library’s code, the implementation seemed to have strange design decision (such as the weird OOP style update on the Issue object you pointed out).

I’m looking to keep the changes to this code fairly minimal since this service is in hibernation until we fully decommission it. At this time, I’m making an API call using requests to short circuit the library update, and that works.

Appreciate the library recommendations!

I’ll re-post in the dev support.

Thank you,
Remi

1 Like

Hi @RemiCarton

We’ve created the following bug to track this.