Expecting property name enclosed in double quotes

The parser was at a point where an object member has to begin — just after {, or just after a comma — and what it found was not a ". In JSON, keys are strings, and strings are double-quoted. There is no second option.

How the message appears

CPython's json module reports line, column and character offset. The position given is where the key should have begun, not where the mistake was typed.

  • json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 2 column 3 (char 4)
  • json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 4 column 1 (char 38)

What causes it

A printed Python dict

str({'name': 'Ada'}) gives {'name': 'Ada'}, which looks so close to JSON that it gets pasted into files and request bodies constantly. Single quotes are the giveaway. This is the single most common source of this message.

A trailing comma before the closing brace

The comma promises another member and } is not one, so the parser complains about the missing key rather than about the comma. The reported column is the closing brace, one line below the real mistake.

Unquoted keys

{name: "Ada"} is a valid JavaScript object literal and invalid JSON. Anything copied out of JS source, a YAML file or a MongoDB shell will land here.

A comment inside the object

JSON has no comments. A # or // line between members puts a non-" character exactly where a key was expected.

The fix

Use double quotes for every key and every string value, and remove any comma that sits before a } or ]. If the text came from Python, regenerate it with json.dumps(obj) instead of str(obj) or an f-string.

Fails to parse
{
  'name': 'Ada',
  'roles': ['admin', 'editor']
}
Parses
{
  "name": "Ada",
  "roles": ["admin", "editor"]
}

The example travels in the URL fragment, which browsers never send to a server.

Worth knowing

  • If the input genuinely is Python source rather than JSON, ast.literal_eval is the right tool for it. It is not a JSON parser, and it is not a substitute for one.
  • Python's own error is more helpful than it looks: the reported char offset is where the key should have started, so the mistake is almost always the character immediately before it.

Your JSON and text are processed entirely in your browser and are never sent anywhere. To understand how the site is used we record each page view — the page, the referrer and an approximate location from your IP address — and keep it for 90 days. Nothing is stored on your device unless you choose it. Accept to also store a device identifier here and record your browser and device characteristics, which is what lets a return visit be told from a new one. Decline and nothing is sent at all. We respect Do Not Track. See our privacy policy.