response.status_code==200 when Bean is not found and status=404

I experience some strange behavior about response.status_code.

If I do an invalid request (in this sample case, I put on purpose an incorrect Bean name), I still get response.status_code=200 while I expect some error code (such as 404)

Even more strange, in the JSON, there is indeed a status:404 (see sample code and outputs below)


## Expected Result

status should be 404 in such case

## Actual Result

I got a status==200, meaning 'no error'

## Reproduction Steps

How is it that this JSON info does not get to the response.status_code?

Here is the sample code:

        req = baseUrl + "/exec/bean:name=AnInvalidBean/send([D,boolean,boolean)/1,2,3,4,0.5,0.6,13,10/True/True”
        response = self.GET(req, 10)
        test.log("   RESPONSE = " + str(response))
        test.log("   JSON: " + str(response.json()))
        test.log("   response.status_code: " + str(response.status_code))
        test.log("   response.json().get(\"status\"): " + str(response.json().get("status")))
        test.log("   response.ok: " + str(response.ok))
        test.log("   response as a boolean: " + str(True if response else False))

And the corresponding log (re-formatted for readability):

        REQUEST : http://127.0.0.1:5555/jolokia/exec/bean:name=NONExistingBean/send([D,boolean,boolean)/1,2,3,4,0.5,0.6,13,10/True/True 

        RESPONSE = <Response [200]> 

        JSON: {
        'request': 
        {
        'mbean': 'bean:name=NONExistingBean', 
        'arguments': ['1,2,3,4,0.5,0.6,13,10', 'True', 'True'], 
        'type': 'exec', 
        'operation': 'send([D,boolean,boolean)'
        }, 
        'stacktrace': 'javax.management.InstanceNotFoundException: bean:name=NONExistingBean\r\n\tat  […TRUNCATED…] at java.base/java.lang.Thread.run(Thread.java:834)\r\n', 
        'error_type': 'javax.management.InstanceNotFoundException', 
        'error': 'javax.management.InstanceNotFoundException :      bean:name=UsddderPositionSenderPanelTestFacade', 
        'status': 404
        }

        response.status_code: 200 
        response.json().get("status"): 404 

        response.ok: True 
        response as a boolean: True 


How can we get these 2 ‘conflicting’ lines:
response.status_code: 200 
response.json().get("status"): 404 
How is it that despite the 'status': 404, the ‘stacktrace’ and ‘error’, I still get status_code: 200? 
I’m using requests          2.22.0


## System Information

python -m requests.help
{
  "chardet": {
    "version": "3.0.4"
  },
  "cryptography": {
    "version": ""
  },
  "idna": {
    "version": "2.8"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.7.4"
  },
  "platform": {
    "release": "10",
    "system": "Windows"
  },
  "pyOpenSSL": {
    "openssl_version": "",
    "version": null
  },
  "requests": {
    "version": "2.22.0"
  },
  "system_ssl": {
    "version": "1010103f"
  },
  "urllib3": {
    "version": "1.25.8"
  },
  "using_pyopenssl": false
}


>  How is it that despite the 'status': 404, the ‘stacktrace’ and ‘error’, I still get status_code: 200?

You're not actually setting the status of the response in the server but returning the 404 as part of the data. You need to read something that explains how HTTP works because there is no bug in this project. 

I don't think this is a problem with `requests`, however, it is a problem with the response given by the server due to it not actually returning a 404 HTTP response code. Read the docs of whatever webserver you are using.

Thanks you both for the hint. We don't write the server, we use Jolokia and indeed they make the difference between the HTTP level error code and the actual processing of the request.
This is even in their doc: https://jolokia.org/reference/html/protocol.html
Sorry for the annoyance and thanks for the great tool.

@ovierlinck no worries!