How to Fix 422 Client Error: Unprocessable Entity when using the json parameter of Request Python Module
The aim of this page📝 is to explain how to debug and handle errors in Python code based on the particular example of a 422 Client Error: Unprocessable Entity
error that occurred when making a request to an Iglu schema registry.
- A
422 Client Error: Unprocessable Entity
error occurs when the server understands the content type of the request entity, but the server was unable to process the contained instructions. - In this case, the error message indicated that the request body was invalid.
- The cause of this issue is that the data being sent in the request body was not in the expected format.
- The
json
parameter of therequests
library expects a JSON-serializable object, not a string. - If you pass a string to the
json
parameter, it will be sent as-is in the body of the request and will not be serialized to JSON.
Starting with Requests version 2.4.2, you can use the
json=
parameter (which takes a dictionary) instead ofdata=
(which takes a string) in the call: — https://stackoverflow.com/a/26344315/11082684
- To fix this issue, you could deserialize the contents of a JSON file into a Python object before passing it to the
json
parameter. - You can use the
json.load()
function to deserialize the contents of a file into a Python object.
BROKEN CODE
Here is a particular example I have experienced (I know make_iglu_request takes way too many params, will refactor)
def patch_schema(iglu: Iglu) -> None:
...
for env in envs:
...
with handle_patching(schema):
...
with open("temp_schema.json", mode="rt", encoding="utf-8") as patched_schema:
schema_to_patch = patched_schema.read() # <<< ERR!
schema_patcher_http_requestor.make_iglu_request(requests.put,
env,
schema_endpoint,
iglu,
schema_to_patch)
...
def make_iglu_request(request_func: Callable, env: str, schema_endpoint: str, iglu: Iglu, schema_to_patch: json) -> None:
... # 🠉 ERR in the type hint!
try:
res = request_func(url,
headers=headers,
verify=os.environ['CACERT'],
json=schema_to_patch)
...
except requests.exceptions.RequestException as err:
...
This code reads the contents of a file into a string and assigns it to the schema_to_patch
variable. However, this string is then passed to the make_iglu_request
function and ultimately to the json
parameter of the request_func
function. This causes an error because the json
parameter expects a JSON-serializable object, not a string.
422 Client Error: Unprocessable Entity for url: https://com-snowplowanalytics-dev.iglu.snplow.net/api/schemas/com.example-company/onmouse_img/jsonschema/1-0-0
{"message":"The request body was invalid."}
RUBBERDUCK
FIX
To fix this issue, you could change your code to deserialize the contents of the temp_schema.json
file into a Python object before passing it to the make_iglu_request
function. For example, you could change your code to something like this:
with open("temp_schema.json", mode="rt", encoding="utf-8") as patched_schema:
schema_to_patch = json.load(patched_schema)
This will deserialize the contents of the temp_schema.json
file into a Python object, which can then be passed to the make_iglu_request
function and ultimately to the json
parameter of the request_func
function.