{}JSON FYI

Postgres: invalid input syntax for type json — causes and fixes

Why PostgreSQL rejects a value with 'invalid input syntax for type json', how to read the DETAIL line, and the exact fix for single quotes, empty strings, NULs, and double-encoded JSON.

·7 min read

What does "invalid input syntax for type json" mean in Postgres?

PostgreSQL raises this when a value you are inserting into a json or jsonb column is not valid JSON. The DETAIL line tells you exactly where it stopped. The usual causes are single-quoted strings, an empty string instead of NULL, a bare word that should be quoted, a NUL byte (\u0000) inside a string, or JSON that was encoded twice.

Read the DETAIL line first

Postgres always tells you what it expected. The DETAIL is more useful than the headline error:

ERROR:  invalid input syntax for type json
DETAIL:  Token "'" is invalid.
CONTEXT:  JSON data, line 1: {'...

ERROR:  invalid input syntax for type json
DETAIL:  The input string ended unexpectedly.
CONTEXT:  JSON data, line 1: {"a": 1

Cause 1 — single quotes instead of double quotes

This is by far the most common. JSON requires double quotes; single quotes are a SQL string delimiter, not JSON syntax.

-- ✗ Fails: the JSON itself uses single quotes
INSERT INTO t (payload) VALUES ('{'name': 'Ada'}');

-- ✓ Correct: single quotes delimit the SQL literal,
--   double quotes are inside the JSON
INSERT INTO t (payload) VALUES ('{"name": "Ada"}');

-- ✓ Or use dollar quoting to avoid escaping entirely
INSERT INTO t (payload) VALUES ($${"name": "O'Brien"}$$);

Cause 2 — empty string instead of NULL

An empty string is not valid JSON. If a column is nullable, insert NULL; if you need an empty document, insert '{}' or 'null'.

-- ✗ ERROR: invalid input syntax for type json
INSERT INTO t (payload) VALUES ('');

-- ✓ Pick the one you actually mean
INSERT INTO t (payload) VALUES (NULL);      -- no value
INSERT INTO t (payload) VALUES ('{}');      -- empty object
INSERT INTO t (payload) VALUES ('null');    -- JSON null

-- Clean an existing column
UPDATE t SET payload = NULL WHERE payload::text = '';

Cause 3 — a NUL byte in the string

PostgreSQL's jsonb cannot store \u0000, even though it is legal in the JSON spec. This bites when importing scraped or binary-ish data.

ERROR:  unsupported Unicode escape sequence
DETAIL:  \u0000 cannot be converted to text.

-- Strip NULs before inserting
SELECT replace(payload, '\u0000', '')::jsonb;

Cause 4 — double-encoded JSON

If an application JSON-encodes a value that was already a JSON string, Postgres receives a quoted string containing JSON rather than an object. It parses — but as a string, so key lookups return nothing.

-- What arrived (a JSON *string*, not an object):
"{\"name\": \"Ada\"}"

-- Detect it:
SELECT jsonb_typeof(payload) FROM t;   -- 'string' instead of 'object'

-- Recover it:
UPDATE t SET payload = (payload #>> '{}')::jsonb
WHERE jsonb_typeof(payload) = 'string';

Validate before you insert

Postgres 16+ ships an IS JSON predicate, which lets you find bad rows without aborting the statement:

-- Postgres 16+
SELECT * FROM staging WHERE NOT (raw IS JSON);

-- Any version: quarantine bad rows during load
INSERT INTO t (payload)
SELECT raw::jsonb FROM staging
WHERE raw IS NOT NULL AND raw <> '';

Paste your JSON into the validator →

Get the exact line, column, and a fix hint in seconds — no upload, no signup.

Open JSON Validator →

json vs jsonb — does it matter here?

  • json — stores the text almost verbatim; still rejects invalid syntax, but preserves key order and duplicates.
  • jsonb — parses into a binary form: strips whitespace, reorders keys, keeps only the last duplicate key, and rejects \u0000.
  • Both raise invalid input syntax for type json for malformed text, so the fixes above apply to either.

Frequently asked questions

Why does Postgres say invalid input syntax for type json?+

Because the text you tried to store in a json or jsonb column is not valid JSON. Read the DETAIL line of the error — it names the offending token or says the input ended unexpectedly, which points straight at the cause.

Can I insert an empty string into a json column?+

No. An empty string is not valid JSON. Use NULL for no value, '{}' for an empty object, or the literal 'null' for JSON null.

Why do single quotes break JSON in Postgres?+

JSON requires double quotes around strings and keys. In SQL the single quotes delimit the literal, so the JSON inside must use double quotes: '{"name": "Ada"}'. Dollar quoting ($$...$$) avoids escaping headaches.

How do I find which rows contain invalid JSON?+

On Postgres 16+ use the IS JSON predicate: SELECT * FROM staging WHERE NOT (raw IS JSON). On older versions, load into a text column first and validate in batches.

What is the difference between json and jsonb for invalid input?+

Both reject malformed JSON with the same error. jsonb is additionally stricter about \u0000 escapes and normalizes the document (drops whitespace, reorders keys, keeps the last duplicate key).

Related tools & guides