even looking through the code, it is not obvious to me what the possible exceptions might be.

Here's my attempt at looking through it:

def json(self, **kwargs: typing.Any) -> typing.Any:
    if self.charset_encoding is None and self.content and len(self.content) > 3:
        encoding = guess_json_utf(self.content)
        if encoding is not None:
            return jsonlib.loads(self.content.decode(encoding), **kwargs)
    return jsonlib.loads(self.text, **kwargs)
  • self.content can raise ResponseNotRead if (as it sounds like) the response has not been read yet. However, this is almost certainly due to a logical error in the code rather than any meaningful problem at runtime worth detecting; so there is no good reason to catch this. (It also wouldn't happen with the most straightforward use cases, such as the one shown in the documentation.) Otherwise, self.content will be a bytes, so len will work.

  • self.charset_encoding will either return None (if there is no corresponding data in the response header) or else eventually use the standard library email.message.Message.get_content_charset to parse a content type from the response header. The latter is not documented to raise any exceptions; so there should not be any exception from accessing this value.

  • guess_json_utf will necessarily be passed a bytes that is at least 4 bytes long. Nothing in its logic should be able to fail under those conditions. Either None or a string will be returned.

  • If jsonlib.loads is called using self.content.decode(encoding), then encoding was necessarily not None, and is a valid encoding name returned from guess_json_utf However, it's possible that the self.content (bytes data) is not valid data (i.e., convertible to text using the guessed text encoding). This would cause UnicodeDecodeError.

  • Otherwise, it's called with self.text. If the underlying _text was set before, it will be a string and gets returned. If there is no content in the response, an empty string is returned. Otherwise, decoding is attempted using a default text encoder with a "replace" error-handling policy. There again shouldn't be anything that could cause the text encoding name to be invalid, so again this can only raise UnicodeDecodeError, and even that shouldn't be possible with the "replace" error-handling policy.

  • Finally: jsonlib.loads is simply json.loads (i.e., the standard library json). if the code gets this far, json.loads will definitely be given a string to load; all possible issues with the string contents will be reported as JSONDecodeError.


tl;dr: the possible exceptions that make sense to catch are JSONDecodeError (the response is not valid JSON - this includes e.g. an empty response) and UnicodeDecodeError (the response is corrupt in some way, for example it mixes bytes intended to encode text in two different ways, or it's supposed to be UTF-8 but contains bytes that are illegal in that encoding; or it's encoded using a non-UTF scheme, such as Latin-1, in a way that is incompatible with the corresponding guessed UTF scheme, and doesn't advertise the encoding in the header).

Answer from Karl Knechtel on Stack Overflow
🌐
GitHub
github.com › Colin-b › httpx_auth › issues › 92
JSONDecodeError due to Improper Handling of Nested JSON Strings in JWT Payloads · Issue #92 · Colin-b/httpx_auth
April 17, 2024 - json.decoder.JSONDecodeError: Expecting ',' delimiter: line 1 column 12 (char 11) This error is caused by the way double quotes inside the nested JSON are handled, which corrupts the JSON string during the base64 decoding step.
Author   pythrick
Top answer
1 of 1
4

even looking through the code, it is not obvious to me what the possible exceptions might be.

Here's my attempt at looking through it:

def json(self, **kwargs: typing.Any) -> typing.Any:
    if self.charset_encoding is None and self.content and len(self.content) > 3:
        encoding = guess_json_utf(self.content)
        if encoding is not None:
            return jsonlib.loads(self.content.decode(encoding), **kwargs)
    return jsonlib.loads(self.text, **kwargs)
  • self.content can raise ResponseNotRead if (as it sounds like) the response has not been read yet. However, this is almost certainly due to a logical error in the code rather than any meaningful problem at runtime worth detecting; so there is no good reason to catch this. (It also wouldn't happen with the most straightforward use cases, such as the one shown in the documentation.) Otherwise, self.content will be a bytes, so len will work.

  • self.charset_encoding will either return None (if there is no corresponding data in the response header) or else eventually use the standard library email.message.Message.get_content_charset to parse a content type from the response header. The latter is not documented to raise any exceptions; so there should not be any exception from accessing this value.

  • guess_json_utf will necessarily be passed a bytes that is at least 4 bytes long. Nothing in its logic should be able to fail under those conditions. Either None or a string will be returned.

  • If jsonlib.loads is called using self.content.decode(encoding), then encoding was necessarily not None, and is a valid encoding name returned from guess_json_utf However, it's possible that the self.content (bytes data) is not valid data (i.e., convertible to text using the guessed text encoding). This would cause UnicodeDecodeError.

  • Otherwise, it's called with self.text. If the underlying _text was set before, it will be a string and gets returned. If there is no content in the response, an empty string is returned. Otherwise, decoding is attempted using a default text encoder with a "replace" error-handling policy. There again shouldn't be anything that could cause the text encoding name to be invalid, so again this can only raise UnicodeDecodeError, and even that shouldn't be possible with the "replace" error-handling policy.

  • Finally: jsonlib.loads is simply json.loads (i.e., the standard library json). if the code gets this far, json.loads will definitely be given a string to load; all possible issues with the string contents will be reported as JSONDecodeError.


tl;dr: the possible exceptions that make sense to catch are JSONDecodeError (the response is not valid JSON - this includes e.g. an empty response) and UnicodeDecodeError (the response is corrupt in some way, for example it mixes bytes intended to encode text in two different ways, or it's supposed to be UTF-8 but contains bytes that are illegal in that encoding; or it's encoded using a non-UTF scheme, such as Latin-1, in a way that is incompatible with the corresponding guessed UTF scheme, and doesn't advertise the encoding in the header).

Discussions

python requests randomly breaks with JSONDecodeError - Stack Overflow
I have been debugging for hours why my code randomly breaks with this error: JSONDecodeError: Expecting value: line 1 column 1 (char 0) This is the code I have: while True: try: More on stackoverflow.com
🌐 stackoverflow.com
python - Handle JSON Decode Error when nothing returned - Stack Overflow
I am parsing json data. I don't have an issue with parsing and I am using simplejson module. But some api requests returns empty value. Here is my example: { "all" : { "count" : 0, "quest... More on stackoverflow.com
🌐 stackoverflow.com
Custom JSON library
Hi! Is there a way to use an alternative JSON library to decode the request? Like orjson for example? Thanks! More on github.com
🌐 github.com
37
January 3, 2020
Randomly receiving json.decoder.JSONDecodeError error when using requests.get. Completely out of ideas
check the returned content. Decoder is complaining it has to work with None (?) /gets no value. More on reddit.com
🌐 r/learnpython
3
3
September 10, 2016
🌐
GitHub
github.com › encode › httpx › discussions › 2695
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) · encode/httpx · Discussion #2695
I have a script import httpx url = f"https://hn.algolia.com/api/v1/users/morenoh149" response = httpx.get(url) data = response.json() I get this error python try_lib.py Traceback (most recent call ...
Author   encode
🌐
ItsMyCode
itsmycode.com › jsondecodeerror-expecting-value-line-1-column-1-char-0
JSONDecodeError: Expecting value: line 1 column 1 (char 0) - ItsMyCode
October 15, 2024 - You will get jsondecodeerror: expecting value: line 1 column 1 (char 0) if the request is empty or the content type is not application/json
🌐
Peterbe.com
peterbe.com › plog › jsondecodeerror-in-requests.get.json-python-2-and-3
Cope with JSONDecodeError in requests.get().json() in Python 2 and 3 - Peterbe.com
import json import requests try: from json.decoder import JSONDecodeError except ImportError: JSONDecodeError = ValueError response = requests.get(url) try: print(response.json()) except JSONDecodeError: print("N'est pas JSON")
🌐
Techstaunch
techstaunch.com › blogs › json-decoder-jsondecodeerror-expecting-value-line-1-column-1-char-0-how-to-solve
json.decoder.jsondecodeerror: expecting value: line 1 column 1 (char 0) How to Fix, Solve
August 21, 2024 - The JSONDecodeError commonly occurs when trying to decode a JSON object in Python and the input data is not in valid JSON format.
Top answer
1 of 3
11

Looking at the documentation for this API it seems the only responses are in JSON format, so receiving HTML is strange. To increase the likelihood of receiving a JSON response, you can set the 'Accept' header to 'application/json'.

I tried querying this API many times with parameters and did not encounter a JSONDecodeError. This error is likely the result of another error on the server side. To handle it, except a json.decoder.JSONDecodeError in addition to the ConnectionError error you currently except and handle this error in the same way as the ConnectionError.

Here is an example with all that in mind:

import requests, json, time, random

def get_submission_records(client, since, try_number=1):
    url = 'http://reymisterio.net/data-dump/api.php/submission?filter[]=form,cs,'+client+'&filter[]=date,cs,'+since
    headers = {'Accept': 'application/json'}
    try:
        response = requests.get(url, headers=headers).json()
    except (requests.exceptions.ConnectionError, json.decoder.JSONDecodeError):
        time.sleep(2**try_number + random.random()*0.01) #exponential backoff
        return get_submission_records(client, since, try_number=try_number+1)
    else:
        return response['submission']['records']

I've also wrapped this logic in a recursive function, rather than using while loop because I think it is semantically clearer. This function also waits before trying again using exponential backoff (waiting twice as long after each failure).

Edit: For Python 2.7, the error from trying to parse bad json is a ValueError, not a JSONDecodeError

import requests, time, random

def get_submission_records(client, since, try_number=1):
    url = 'http://reymisterio.net/data-dump/api.php/submission?filter[]=form,cs,'+client+'&filter[]=date,cs,'+since
    headers = {'Accept': 'application/json'}
    try:
        response = requests.get(url, headers=headers).json()
    except (requests.exceptions.ConnectionError, ValueError):
        time.sleep(2**try_number + random.random()*0.01) #exponential backoff
        return get_submission_records(client, since, try_number=try_number+1)
    else:
        return response['submission']['records']

so just change that except line to include a ValueError instead of json.decoder.JSONDecodeError.

2 of 3
0

Catching ValueError is universal across python versions from py2 to py3

For py3 only is better to catch from already imported requests library: requests.JSONDecoderError, so you don't need to import json library.

Top answer
1 of 2
241

There is a rule in Python programming called "it is Easier to Ask for Forgiveness than for Permission" (in short: EAFP). It means that you should catch exceptions instead of checking values for validity.

Thus, try the following:

try:
    qByUser = byUsrUrlObj.read()
    qUserData = json.loads(qByUser).decode('utf-8')
    questionSubjs = qUserData["all"]["questions"]
except ValueError:  # includes simplejson.decoder.JSONDecodeError
    print('Decoding JSON has failed')

EDIT: Since simplejson.decoder.JSONDecodeError actually inherits from ValueError (proof here), I simplified the catch statement by just using ValueError.

2 of 2
56

If you don't mind importing the json module, then the best way to handle it is through json.JSONDecodeError (or json.decoder.JSONDecodeError as they are the same) as using default errors like ValueError could catch also other exceptions not necessarily connected to the json decode one.

from json.decoder import JSONDecodeError


try:
    qByUser = byUsrUrlObj.read()
    qUserData = json.loads(qByUser).decode('utf-8')
    questionSubjs = qUserData["all"]["questions"]
except JSONDecodeError as e:
    # do whatever you want

//EDIT (Oct 2020):

As @Jacob Lee noted in the comment, there could be the basic common TypeError raised when the JSON object is not a str, bytes, or bytearray. Your question is about JSONDecodeError, but still it is worth mentioning here as a note; to handle also this situation, but differentiate between different issues, the following could be used:

from json.decoder import JSONDecodeError


try:
    qByUser = byUsrUrlObj.read()
    qUserData = json.loads(qByUser).decode('utf-8')
    questionSubjs = qUserData["all"]["questions"]
except JSONDecodeError as e:
    # do whatever you want
except TypeError as e:
    # do whatever you want in this case
Find elsewhere
🌐
GitHub
github.com › encode › httpx › issues › 717
Custom JSON library · Issue #717 · encode/httpx
January 3, 2020 - Hi! Is there a way to use an alternative JSON library to decode the request? Like orjson for example? Thanks!
Author   victoraugustolls
🌐
Reddit
reddit.com › r/learnpython › randomly receiving json.decoder.jsondecodeerror error when using requests.get. completely out of ideas
r/learnpython on Reddit: Randomly receiving json.decoder.JSONDecodeError error when using requests.get. Completely out of ideas
September 10, 2016 -

I really dont know what is going on...sometimes i am able to get 1-3 records, and other times i can get around 100 before the error appears. There is no consistency. This is how i have my request:

token = lms_token
url = endpoint
headers = {
    "Authorization": "bearer " + str(token),
    "Content-Type": "application/json;odata.metadata=minimal",
    "Accept": "application/json"
}
r = requests.get(url, headers=headers).json()

print(r)

Is there something i need to decode or change to prevent that error from happening? Here is the full error i receive:

File "C:\Users\name\Documents\lib\json_init_.py", line 319, in loads return _default_decoder.decode(s) File "C:\Users\name\Documents\lib\json\decoder.py", line 339, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "C:\Users\name\Documents\lib\json\decoder.py", line 357, in raw_decode raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Thanks!

🌐
Moon Technolabs
moontechnolabs.com › qanda › json-decoder-error
How to Resolve JSON Decoder Error?
June 6, 2025 - try: response = requests.get("https://api.example.com/data") data = response.json() # This works if response contains valid JSON except requests.exceptions.RequestException as e: print(f"Error: {e}") except json.JSONDecodeError: print("Error: Invalid JSON response")
🌐
LSEG Developer Community
community.developers.refinitiv.com › home › eikon data apis
JSONDecodeError in Python API - LSEG Developer Community
October 19, 2020 - When I try to retrieve data using the Pyhon API, I get a JSONDecodeError. I am using Python 3.8.5 (64-bit) on Windows 10 and version 1.1.6.post3 of the eikon package. The same code worked fine, i.e. produced the expected results, a couple of months ago. I updated the eikon package after I got ...
🌐
GitHub
github.com › psf › requests › issues › 6628
[BUG] JSONDecodeError can't be deserialized - invalid JSON raises a BrokenProcessPool and crashes the entire process pool · Issue #6628 · psf/requests
January 31, 2024 - After investigation, this is because the requests.exception.JSONDecodeError instances can't be deserialized once they've been serialized via pickle.
Author   Tarty
🌐
GitHub
github.com › psf › requests › issues › 5794
response.json() raises inconsistent exception type · Issue #5794 · psf/requests
April 16, 2021 - There are some comments about this on #4842 but I think it warrants its own issue. If simplejson is present in the environment, the library uses it so .json() returns simplejson.errors.JSONDecodeError rather than json.decoder.JSONDecodeE...
Author   rowanseymour
🌐
Atlassian Community
community.atlassian.com › q&a › bitbucket › questions › json.decoder.jsondecodeerror when trying to run my pipeline
Solved: json.decoder.JSONDecodeError when trying to run my...
May 4, 2021 - Traceback (most recent call last): File "/main.py", line 170, in <module> pipe.run() File "/main.py", line 68, in run data = json.load(f) File "/usr/local/lib/python3.7/json/__init__.py", line 296, in load parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw) File "/usr/local/lib/python3.7/json/__init__.py", line 348, in loads return _default_decoder.decode(s) File "/usr/local/lib/python3.7/json/decoder.py", line 337, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/usr/local/lib/python3.7/json/decoder.py", line 353, in raw_decode obj, end = self.scan_once(s, idx) json.decoder.JSONDecodeError: Expecting ',' delimiter: line 14 column 41 (char 312)
🌐
Python.org
discuss.python.org › ideas
JSONDecodeError exception's message - verbose - Ideas - Discussions on Python.org
July 17, 2024 - Issue One of the porposes of exception’s message is to help the developer to identify the root cause of the bug and fix it. Currently, JSONDecodeError doesn’t do it well enough. Consider the following example: import json import requests try: server_raw_response = requests.get(url) server_json_response = json.loads(server_raw_response) except JSONDecodeError as error: print(error) # JSONDecodeError: Expecting , delimiter: line 1 column 23 (char 22) Can you understand what is th...
🌐
Stack Overflow
stackoverflow.com › questions › tagged › jsondecodeerror
Newest 'jsondecodeerror' Questions - Stack Overflow
I am trying to parse the content of an API response, which is of the type application/json. However, I am getting the following error: JSONDecodeError: Extra data: line 1 column 2 (char 1) The API ...
Top answer
1 of 16
322

Your code produced an empty response body; you'd want to check for that or catch the exception raised. It is possible the server responded with a 204 No Content response, or a non-200-range status code was returned (404 Not Found, etc.). Check for this.

Note:

  • There is no need to decode a response from UTF8 to Unicode, the json.loads() method can handle UTF8-encoded data natively.

  • pycurl has a very archaic API. Unless you have a specific requirement for using it, there are better choices.

Either requests or httpx offer much friendlier APIs, including JSON support.

If you can, replace your call with the following httpx code:

import httpx

response = httpx.get(url)
response.raise_for_status()  # raises exception when not a 2xx response
if response.status_code != 204:
    return response.json()

Of course, this won't protect you from a URL that doesn't comply with HTTP standards; when using arbitrary URLs where this is a possibility, check if the server intended to give you JSON by checking the Content-Type header, and for good measure catch the exception:

if (
    response.status_code != 204 and
    response.headers["content-type"].strip().startswith("application/json")
):
    try:
        return response.json()
    except ValueError:
        # decide how to handle a server that's misbehaving to this extent
2 of 16
261

Be sure to remember to invoke json.loads() on the contents of the file, as opposed to the file path of that JSON:

json_file_path = "/path/to/example.json"

with open(json_file_path, 'r') as j:
     contents = json.loads(j.read())

I think a lot of people are guilty of doing this every once in a while (myself included):

contents = json.load(json_file_path)
🌐
Django Forum
forum.djangoproject.com › using django › forms & apis
What does this django error mean? JSONDecodeError at '/url-path/' Expecting value: line 1 column 1 (char 0) - Forms & APIs - Django Forum
May 13, 2023 - I frequently encounter this problem when using Django and Python in general; it seems to occur everytime I attempt to make an api call or other similar operation. I am trying to onboard users to PayPal in this case utilizing the PayPal “Referral API,” and after following the documentation, I came up with the following code. def onboard_seller_view_2(request): # Retrieve seller's information from the request seller_name = request.POST.get('name') seller_email = request.POST.get('ema...