How to interpret 400, 403 and 404 errors returned by POST /rest/api/2/search?

We have an external OAuth2 (3LO) app that consumes the Jira REST API. This external app needs to know if our Jira Connect app is installed or not. Like others we are using a workaround to detect this:

Our Connect app declares searchable entity properties. Searchable entity properties are not accessible via OAuth2 (3LO). So we call POST /rest/api/2/search using a JQL including any searchable property from our connect app. If that request fails with a 400 error we conclude that the Connect app is not installed.

Through testing on our own Jira instances, we figured that if the app is not installed the Jira REST API returns a 400 error. However, in recent logs, we also noticed 403 errors including the error message The app is not installed on this instance, 404 errors (see below for example responses), and a few 500s (500s seem to happen here and there - the practice here seems to just retry).

The API docs on POST /rest/api/2/search only document the 400 and 401 errors.

Can anyone tell us:

  1. Why does the API sometimes return 400 errors and other times 403 errors both indicating that the Connect app is not installed? We are trying to find a consistent way to detect if our connect app is installed or not.
  2. What does the 404 error mean and why does it appear?

If anyone knows a better approach to detect if a Jira Connect app is installed via the Jira REST API and an OAuth2 (3LO) app please let us know.

Btw, we are aware of this request which is related to detecting an apps installation status but it seems the focus is on Connect: https://ecosystem.atlassian.net/browse/AC-2530

Example 403 response:

{
	"response": {
		"statusText": "Forbidden",
		"status": 403,
		"header": {
			"date": "Wed, 03 Mar 2021 08:14:24 GMT",
			"micros-issuer": "micros/edge-authenticator",
			"x-request-id": "1afcae5741fc5946",
			"transfer-encoding": "chunked",
			"connection": "close",
			"server": "envoy",
			"x-envoy-upstream-service-time": "33",
			"x-arequestid": "e6a263e9-943b-40e7-8467-7ac4502b3f40",
			"timing-allow-origin": "*",
			"x-trace-id": "1afcae5741fc5946",
            // ... some removed headers
		},
		"data": {
			"errorMessages": [
				"The app is not installed on this instance."
			]
		}
	},
	"request": {
		"method": "POST",
		"path": "/ex/jira/<redacted-cloud-id>/rest/api/2/search"
	}
}

Example 404 response:

{
	"response": {
		"data": {
			"error": "Not Found",
			"message": "No message available",
			"timestamp": "2021-03-03T06:29:52.160Z",
			"status": 404,
			"path": "/ex/jira/<redacted-cloud-id>/rest/api/2/search"
		},
		"statusText": "Not Found",
		"status": 404,
		"header": {
			"x-failure-category": "FAILURE_CLIENT_TCS",
			"content-length": "179",
			"x-trace-id": "9e27dbe50f591329",
			"connection": "close",
			"x-request-id": "9e27dbe50f591329",
			"date": "Wed, 03 Mar 2021 06:29:52 GMT",
            // ... additional removed headers
		}
	},
	"request": {
		"path": "/ex/jira/<redacted-cloud-id>/rest/api/2/search",
		"method": "POST"
	}
}
2 Likes

Hi @tbinna ,

Thanks for providing such a thorough post. I’ve created ACJIRA-2345 for the Jira Cloud team to document the API properly.

Looking at the 404 response, TCS is an internal acronym for tenant context service so I can imagine some sort of lookup occurred which failed due to the app not being installed. Guessing further, these types of lookups are often cached so perhaps the the randomness of the 403 and 404 is related to different paths based on caching? If this is the case, it would seem the 404 response should be translated into a more appropriate response code.

Regards,
Dugald