WebHooks or Web Requests fail with HTTP Status Code 400, 401 or 403 in Jira
Platform Notice: Data Center - This article applies to Atlassian products on the Data Center platform.
Note that this KB was created for the Data Center version of the product. Data Center KBs for non-Data Center-specific features may also work for Server versions of the product, however they have not been tested. Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.
*Except Fisheye and Crucible
Summary
This article helps understand and troubleshoot the different HTTP Statuses a request can receive either going out of Jira (WebHooks or Web Requests) or going into Jira (REST API, etc).
The requests receive a status code to tell the client what happened to the response — if it was successful or not, and if not, a hint towards what the issue may be.
Here's the RFC 9110 definition of status codes:
- 1xx (Informational): The request was received, continuing process
- 2xx (Successful): The request was successfully received, understood, and accepted
- 3xx (Redirection): Further action needs to be taken in order to complete the request
- 4xx (Client Error): The request contains bad syntax or cannot be fulfilled
- 5xx (Server Error): The server failed to fulfill an apparently valid request
Errors 4xx and 5xx are the most common when integrating Jira and other apps. 4xx means the fault was on the client side (the request wasn't made properly), while 5xx indicates the request might've been OK but it was the server that failed to process the request properly.
Some common errors we see to and from Jira (with a brief explanation) are:
- 400: Bad Request — A catch all code for things not represented by other codes
- 401: Unauthorized — When the server was not able to identify the user due to missing credentials or credentials passed in a wrong manner
- 403: Forbidden — The server was able to identify the user but the user doesn't have permission to execute what the request asked for
- 404: Not Found — The resource requested doesn't exist (yet?)
- 500: Internal Server Error — A catch all code for anything that went wrong on the server and the request couldn't be (completely?) fulfilled
- 503: Service Unavailable — The server is known to be down or unavailable to process this request
- 504: Gateway Timeout — The request took to long to complete and was cut off by a proxy somewhere between the client and the destination server
Please keep in mind that the meaning of HTTP Status Codes is from the specification and some services may implement them slightly differently.
Environment
Any version of Jira Software or Jira Service Management Data Center.
Diagnosis
Usually the HTTP status code is clearly visible on requests responses and logs, though sometimes you may need to enable DEBUG log if it's not present.
If you're working with WebHooks from Jira, you may refer to Troubleshooting WebHooks in Jira Data Center.
As introduced above, 4xx errors are usually "the client's fault" and 5xx is usually "the destination server's fault".
For both scenarios, request FROM and TO Jira, we should always reproduce the request outside the system (Jira or client app) — with a REST API client like Postman or preferably, through a command line tool like curl. Command line's interesting because we can build the request in a raw form and have total control of what's being passed and how. Some REST API clients may mask the real request behind the User Interface and we may not know how the request's being performed exactly so we can later port it to Jira or the client app.
It's advised to get the request working first on the command line and only then port it back to Jira or the client app.
Causes and Solutions
We break down some common causes and what to look for on each of them.
Again, keep in mind products or systems can use these codes differently. Below is what we'd expected should they implement the specification adequately.
400: Bad Request
This is the catch-all code for something wrong in the request (that's not related to user credentials).
Some common causes are:
- The Content-Type was not specified on the request, like
-H "Content-Type: application/json"
in curl. This is often seen on PUT/POST requests. - The request contain an invalid command, like when performing invalid JQL searches in Jira (with a project that doesn't exist or the user's not authenticated), Jira returns a 400 status because the JQL's malformed/invalid.
- When using PUT or POST, the content of the request may be invalid or ill-formatted, like an invalid JSON content.
This may cause some confusion in Jira /search REST API. If Jira allows anonymous access and there's a restricted Project, querying for it will return a HTTP 400, not 401 or 403. It'll respond for example "The value 'PKEY' does not exist for the field 'project'." and that's considered an invalid request, thus it responds with 400. If this is the case, treat it as a 401/403 error and try passing the correct credentials so the JQL works.
401: Unauthorized
This error is usually when the credentials for the user performing the request aren't provided in the right way or are invalid. i.e. the service wasn't able to identify the user.
Examples causes include:
- Typo on the header names, like "Autorization" instead of "Authorization", "CUSTOM-AUTH" instead of "CUSTOM_AUTH" for example
- A token that's invalid or expired
- The user credential missing completely from the request. It's usually in the form of Headers like
-H "Authorization: ..."
in curl
Keep troubleshooting the request on curl until you get it working. Refer to the destination service's documentation on how to pass the credentials properly (which headers it uses and such).
For example Jira Cloud uses API Token which is in the format -H "Authorization: Basic *****"
while Jira Data Center uses the Personal Access Token like -H "Authorization: Bearer *****"
. Notice the difference between Basic and Bearer — it's a detail but won't work if not built like that.
403: Forbidden
This usually means the server was able to identify the user (we're out of the 401 error) but this user doesn't have the required permissions to perform this request.
For troubleshooting purposes, you can try passing the credentials (tokens, etc) of an Admin User on the destination service that you're sure they have access/permission on that. It's also a good idea to test that same user through the User Interface to see if the user really has access on the projects, spaces or resources we're trying to access through the REST API.
404: Not Found
The resource being requested doesn't exist — maybe yet (if it's just been created, for example and the system relies on replication and such).
This is considered a "client error" because it's the client that requested for a resource that doesn't exist. If they change the resource for another one (like another Issue, or another file or pull request, etc) it should work.
500: Internal Server Error
Something on the destination server prevented it from fulfilling the request. Depending on how the destination service works, the request may have been fulfilled partially, like when Jira creates an Issue but a Workflow post-function fails — the Issue was actually created but will only be searchable after it's reindexed again (individually or after a Full Reindex).
We'll have to check the logs of the destination service to understand what might've happened.
This may be a temporary error or a persistent one. Retrying the request may result in success or not, it depends on what the root cause was and how the destination service works.
503: Service Unavailable
The destination service's unable to even receive the request and this response's usually given by a proxy between the client and the service.
In Jira this may mean the nodes are down, the Load Balancer is down or the nodes have ran out of Tomcat Threads, meaning they're all too busy and can't take any more requests at the moment.
This is usually a temporary error and while retrying may work, it may be wise to allow some time to pass before retrying again (as if giving the destination service some time to recover).
504: Gateway timeout
When we get this error, it means the connection "took too long" to complete was abruptly cut short by an intermediate proxy between the client and the destination server. It can be either the "outbound proxy" (here all the requests from the client go through) or the "reverse proxy" (where all the requests to the destination service go through).
The "too long" is usually configurable on the proxies. Some have a default of 60 seconds and if the 504 error happens at the same elapsed time, it's usually a hint that that's the configured timeout. While it's interesting to not have this timeout too high, some requests may need a longer timeout by design. Like a complex report being requested that takes a few minutes to complete. (although it's good practice to have the request generate a background task on the server, many services don't work like that yet and need to time to complete the request).
What we usually observe is that on the destination service the request continues to run as if the client's still waiting for it and may even eventually complete successfully! It's worth waiting some more then checking it the request was not indeed actually processed successfully before retrying, though it's also best to either optimize the request or increase the "idle timeout" on whatever proxy's in the way.