Skip to content
Commitpedia
Log in Join & edit

Fix: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Python's json module found nothing it could parse at the very first character. The input is usually empty, HTML, or already consumed. Print the raw text first, then fix the source.

Drafted with AI from official documentation. Scripts were run in a test environment and repository links verified. Awaiting a human check. Did it work for you? Last edited Outdated?

Edit history of Fix: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0): 1 recorded edit
Edit history · 1 edit
Type
Article
Edits
1
Editors
1
First issued
15 Oct 2026
Last edit
15 Oct 2026
Reading
2 min

Your Python program stops with:

json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

The parser expected a JSON value (an object, array, string, number, true, false or null) at the very first character and did not find one. The message describes the input, not your code, so the first step is always to look at the input.

Step 1: print what you actually received

print(repr(text[:200]))   # repr shows empty strings, whitespace and hidden characters

Cause 1: the input is empty

json.loads("") raises exactly this error. Typical sources are an empty file, a file still being written by another process, or an HTTP response with no body, such as status 204 No Content.

Cause 2: you got HTML or plain text instead of JSON

If the output starts with < or <!doctype html>, the server sent a web page, often a login page, an error page or a rate-limit notice. Check the status code and the Content-Type header before parsing:

import json
import urllib.request

with urllib.request.urlopen("https://api.example.com/items") as resp:
    body = resp.read().decode("utf-8")
    ctype = resp.headers.get("Content-Type", "")

if "json" not in ctype:
    raise RuntimeError(f"expected JSON, got {ctype!r}: {body[:200]!r}")
data = json.loads(body)

urllib raises HTTPError for 4xx and 5xx responses. With the third-party requests library, call response.raise_for_status() before response.json(), so an error page fails with a clear message instead of a parse error.

Cause 3: the file was already read

A file object has a read position. After f.read(), the position is at the end, and a following json.load(f) sees an empty string:

with open("data.json", encoding="utf-8") as f:
    raw = f.read()
    data = json.load(f)      # fails: nothing left to read

with open("data.json", encoding="utf-8") as f:
    raw = f.read()
data = json.loads(raw)       # parse the string you already have

Related messages

  • Unexpected UTF-8 BOM (decode using utf-8-sig): the file starts with a byte order mark. Open it with encoding="utf-8-sig".
  • Extra data: line 2 column 1: the file holds one JSON object per line (JSON Lines). Parse each line separately.
  • Expecting property name enclosed in double quotes: single quotes (often a Python dict written with str()), or a trailing comma. Write files with json.dump().

A loader with useful errors

This helper handles the BOM, rejects empty files, and shows the text around the problem:

import json
from pathlib import Path

def load_json_file(path):
    text = Path(path).read_text(encoding="utf-8-sig")
    if not text.strip():
        raise ValueError(f"{path} is empty")
    try:
        return json.loads(text)
    except json.JSONDecodeError as err:
        snippet = text[max(err.pos - 40, 0):err.pos + 40]
        raise ValueError(f"{path}: {err.msg} at line {err.lineno}, column {err.colno}: {snippet!r}") from None

def load_json_lines(path):
    with open(path, encoding="utf-8") as f:
        return [json.loads(line) for line in f if line.strip()]

If you control the code that produces the data, the real fix is there: always write with json.dump, write UTF-8, and return a proper status code with a JSON body for errors.

Did this work for you?

No votes yet. Be the first.

If it did not work, the report form below tells the editors what went wrong.

See also

  • 0007 Fix: ModuleNotFoundError: No module named ‘…’ Python cannot find a module you import. Usually the package was installed into a different interpreter or virtual environment than the one… Beginner · Fixes an error · Any system Article Common errors · Environments & packages 15 Oct 2026
  • 0008 Fix: TypeError: ‘NoneType’ object is not subscriptable You used [ ] on a value that is None. Something you expected to return a list, dict or match returned nothing.… Beginner · Fixes an error · Any system Article Common errors 15 Oct 2026
  • 0009 CSV to JSON converter A small command-line tool that turns a CSV file into a JSON array of objects, with optional number detection, custom delimiters and… Beginner · Step by step · Any system Script CSV & JSON · Files & automation 15 Oct 2026
  • 0072 CSV vs JSON: choosing a format and avoiding the classic pitfalls CSV is a simple table of text; JSON holds nested, typed data. Both break in predictable ways: quoting, delimiters, encodings, numbers and… Beginner · Explains an idea · Any system Article CSV & JSON 15 Oct 2026
  • 0075 CSV to JSON converter (Python, standard library) Convert any CSV file with a header row into a JSON array or JSON Lines. Handles quoted fields, a byte order mark,… Beginner · Step by step · Any system Script CSV & JSON · Files & automation 15 Oct 2026
  • 0076 jq recipes: 23 one-liners for JSON on the command line A runnable collection of jq filters for everyday JSON work: pick fields, filter with select, reshape, sort, count, group, pass shell variables,… Intermediate · Cheat sheet · Linux, macOS, Windows Script Command-line tools · jq & JSON on the command line 15 Oct 2026

Repos in the wild

History

Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.

  1. Dominik +3,373 chars

Report a problem

Something wrong, unsafe or copied? Tell the editors.
What is wrong?