← Debugging Guides

阅读中文版本

Python — json.decoder.JSONDecodeError on parsing a response

Debug JSONDecodeError by inspecting the raw bytes actually received, since empty or HTML bodies parse as invalid JSON.

beginnerdebuggingpythonjson

Symptoms

  • json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
  • The parse fails only for some responses or when the server errors
  • response.json() raises while the status code is 200
  • An empty body or an HTML error page is fed to the JSON parser

Possible causes

  • The response body is empty, for example for a 204 or a failed request
  • The server returned HTML or plain text instead of JSON, often an error page
  • The response was already consumed or the encoding is wrong
  • A BOM or leading whitespace confuses the parser

Diagnosis steps

Print the raw body before parsing

python -c "import requests; r=requests.get(url); print(r.status_code, r.headers.get('content-type'), repr(r.text[:200]))"

Interpretation

Showing status, content type and the first bytes reveals whether the body is JSON, empty or HTML.

Check the content type header

curl -i https://api.example.com/resource

Interpretation

A content type of text/html for an API call usually means a proxy or auth page intercepted the request.

Guard the parse with a clear error

python -c "import json; json.loads(body)"

Interpretation

Reproducing the exact exception on the captured bytes confirms which input caused it.

Root cause

The parser received bytes that are not valid JSON, because the body was empty, an error page, or otherwise non-JSON, not because the JSON library is faulty.

Fix

Validate the status and content type before parsing, handle empty bodies explicitly, and surface the raw snippet in the error so future failures are diagnosable.

Verify the fix

Re-request the endpoint and confirm parsing succeeds, or confirm the guard raises a descriptive error for the non-JSON case instead of a bare JSONDecodeError.

Symptom walkthrough

Calling response.json() raises JSONDecodeError, usually Expecting value at line 1 column 1, which means the parser saw no JSON at all. This frequently happens when the body is empty on a 204 response or when an error page or authentication redirect returns HTML. Because the exception is thrown by the JSON parser, it falsely looks like a serialization problem rather than a response content problem.

Fix in practice

Inspect the status code, content type and first bytes before parsing. Treat an empty body as a defined outcome, verify the content type is JSON, and include a snippet of the raw body in any error message you raise. This turns an opaque parser failure into a clear contract violation.

Verification

Repeat the request and confirm parsing succeeds, or confirm that the new guard produces a descriptive error naming the status and content type for the non-JSON case. Either outcome proves the diagnosis.

Diagnostic commands

Check the behavior with commands like these:

python -c "import requests; r=requests.get(url); print(r.status_code, r.headers.get('content-type'), repr(r.text[:200]))"
curl -i https://api.example.com/resource
python -c "import json; json.loads(body)"