Python "JSONDecodeError: Expecting value"
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) is one of the most common tracebacks in Python, and one of the most misread — it looks like a JSON syntax problem, but "line 1 column 1 (char 0)" is telling you the parser failed on the very first character. That's a much narrower, more specific class of bug than a malformed document.
// what "char 0" actually tells you
json.loads() — an API returned nothing, a file was blank, a variable was never populated401/404/500 page, or a login redirect — the body is HTML, not JSON, and it starts with < or plain text, not { or [204 No Content responsethe request succeeded and there's deliberately no body at all — calling response.json() on it is calling json.loads('')json.loads()json.loads() parses a JSON string; json.load() parses an open file object. Passing a path string to loads() tries to parse the path itself as JSON, which is never valid JSON and always fails at char 0json.loads() call and look at what's actually there; the fix is almost always upstream of the parse call, not in it.data = json.loads(open("config.json"))json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
open("config.json") returns a file object, not a string. json.loads() tries to parse that object's repr -- something like <_io.TextIOWrapper name='config.json' ...> -- as JSON, and fails at the first character.with open("config.json") as f:
data = json.load(f) # load(), not loads() -- takes the file object directly// guarding a real HTTP call against this
For the API-response version of this bug, check before parsing rather than catching the exception after the fact — it's the difference between knowing exactly what came back and just knowing something went wrong:
resp = requests.get(url)
resp.raise_for_status() # turn 4xx/5xx into an exception here, not a confusing parse error later
if not resp.text.strip():
raise ValueError(f"{url} returned an empty body")
data = resp.json() # or: json.loads(resp.text)// when it's a real position, not char 0
If the line/column/char numbers point somewhere other than the very start, you do have actual JSON that's genuinely malformed partway through — a trailing comma, an unterminated string, a stray invisible character copied in from somewhere else. That's a different, narrower problem than this guide covers, and the JSON Formatter will point at the exact spot and auto-fix what it can.
A real JSON syntax error — a missing comma, an unquoted key — points somewhere inside the document, at whatever token the parser choked on. Char 0 means the parser found nothing to even start on. In practice that means one of these, roughly in order of how often each actually shows up: