How to handle HTTP 400 Bad Request errors on Jira search REST API endpoint
Platform Notice: Data Center Only - This article only 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
Jira's /search REST API endpoint may return a HTTP 400 status code on a few different situations:
Infrastructure or config limits
Invalid JQL query
Non-existing data directly referenced in the JQL query
Unauthenticated user or expired session
Ref.: https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/search
Environment
All versions of Jira Software Data Center or Server.
All versions of Jira Service Management Data Center or Server.
Solution
Infrastructure or config limits
A search request for Jira may return HTTP 400 in case the header size exceeds what's configured in Tomcat or on proxies from the Browser/client to Jira.
Please refer to Jira users receiving the error 400 Bad Request: Message Request header is too large for more on this and how to fix it.
Invalid JQL query
Jira may return a HTTP 400 "Bad Request" if the JQL query is invalid, like containing misspelled keywords or search terms.
The response body will contain a JSON "errorMessages" representation suggesting what the problems may be, like "Field '...' does not exist or you do not have permission to view it":
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ curl -X GET "https://jira-base-url/rest/api/2/search?maxResults=0&fields=id&jql=Projectss+=+KANBAN" -D- -b cookie
HTTP/2 400
cache-control: no-cache, no-store, no-transform
content-security-policy: frame-ancestors 'self'
content-type: application/json;charset=UTF-8
date: Tue, 21 Mar 2023 18:40:44 GMT
referrer-policy: strict-origin-when-cross-origin
strict-transport-security: max-age=31536000
vary: User-Agent
x-arequestid: 1120x206x1
x-asessionid: 629cgy
x-ausername: admin
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-seraph-loginreason: OK
x-xss-protection: 1; mode=block
{"errorMessages":["Field 'Projectss' does not exist or you do not have permission to view it."],"errors":{}}
You can also validate the JQL query by performing the same search on Jira's UI and benefit from the autocomplete feature to fix it.
ℹ️ Note: If a user doesn't have permission to a filter used in the search, this can cause the JQL to become invalid, depending on the functions used.
Non-existing data directly referenced in the JQL query
Jira also responds HTTP 400 "Bad Request" if the JQL query makes explicit reference to inexistent entities, like a specific Issue Key, Issue Type, Project, etc.
This may make searches out of dynamic queries trickier to handle, as there are many variations:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
% curl -X GET "https://jira-base-url/rest/api/2/search?maxResults=0&fields=id&jql=Project+=+KANBAN3+or+key=KANBAN-123456789+or+issuetype+=+test" -D- -b cookie
HTTP/2 400
cache-control: no-cache, no-store, no-transform
content-security-policy: frame-ancestors 'self'
content-type: application/json;charset=UTF-8
date: Tue, 21 Mar 2023 18:47:53 GMT
referrer-policy: strict-origin-when-cross-origin
strict-transport-security: max-age=31536000
vary: User-Agent
x-arequestid: 1127x211x1
x-asessionid: 629cgy
x-ausername: admin
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-seraph-loginreason: OK
x-xss-protection: 1; mode=block
{"errorMessages":["The value 'KANBAN3' does not exist for the field 'Project'.","An issue with key 'KANBAN-123456789' does not exist for field 'key'.","The value 'test' does not exist for the field 'issuetype'."],"errors":{}}
A possible way to handle this is through parsing the response body for the "does not exist for field" text.
Unauthenticated user or expired session
Another tricky scenario of HTTP 400 on searches is then the authentication's not successful.
Jira may respond with HTTP 401 "Unauthorized" status code but also with 400 on some scenarios:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ curl -X GET "https://jira-base-url/rest/api/2/search?maxResults=0&fields=id&jql=Project+=+KANBAN3+or+key=KANBAN-123456789+or+issuetype+=+test" -D- -b file-not-found
HTTP/2 400
cache-control: no-cache, no-store, no-transform
content-security-policy: frame-ancestors 'self'
content-type: application/json;charset=UTF-8
date: Tue, 21 Mar 2023 19:00:09 GMT
referrer-policy: strict-origin-when-cross-origin
set-cookie: _3fe60=5306db38bdb567e7; Path=/
set-cookie: atlassian.xsrf.token=B62A-AHZH-LVWK-Y915_8c35797b5961460eda8dd6340ab2f57162c3365c_lout; Path=/jira; Secure
strict-transport-security: max-age=31536000
vary: User-Agent
x-arequestid: 1140x212x1
x-ausername: anonymous
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
{"errorMessages":["The value 'KANBAN3' does not exist for the field 'Project'.","An issue with key 'KANBAN-123456789' does not exist for field 'key'.","Field 'issuetype' does not exist or this field cannot be viewed by anonymous users."],"errors":{}}
Notice the search request is exactly the same as the previous example — and the response text is very similar, too. The only difference is the request is using a non-existing cookie file (to force the error).
Depending on the JQL query, the response may or may not contain the text "cannot be viewed by anonymous users".
In this case, an alternative is to check for the x-ausername Response Header — notice how it reports the authenticated user "admin" on the previous example and "anonymous" on this latter:
1
2
3
4
5
6
7
8
HTTP/2 400
x-arequestid: 1127x211x1
x-asessionid: 629cgy
x-ausername: admin
HTTP/2 400
x-arequestid: 1140x212x1
x-ausername: anonymous
If a HTTP status code of either 401 or 400 is received on the search endpoint, you may check for the x-ausername Response Header.
If it's "anonymous", you may re-authenticate and try the search again.
Was this helpful?