How to fix Non-unique keys in JSON object in PostgreSQL

PostgreSQLINTERMEDIATEMEDIUMUpdated Dec 26, 2025ยท 110 views

PostgreSQL enforces unique keys in JSON objects, especially with jsonb and PostgreSQL 15+ SQL/JSON functions. This error occurs when you try to create or construct a JSON object with duplicate keys. Ensure all keys in your JSON objects are unique.

Quick fix

Fixes Non-unique keys in JSON object

-- This FAILS - "name" appears twice
SELECT json_object(
  'name', 'Alice',
  'age', 30,
  'name', 'Bob'  -- duplicate key
);
  1. Identify duplicate keys in your JSON construction
  2. Ensure all keys are unique in json_object() calls
  3. Deduplicate keys in json_object_agg() queries
  4. Use UNION/UNION ALL carefully in JSON construction
postgresql โ€” error
-- This FAILS - "name" appears twice
SELECT json_object(
'name', 'Alice',
'age', 30,
'name', 'Bob' -- duplicate key
);
Non-unique keys in JSON object

What this error means

In PostgreSQL, JSON objects are collections of key-value pairs where each key must be unique. When you use functions like json_object, jsonb_object_agg, or construct JSON with duplicate keys, PostgreSQL raises an error to prevent invalid JSON structures. The behavior differs slightly depending on the JSON type you use. The json type (plain text) can technically store duplicate keys in the string representation, but newer SQL/JSON functions and the jsonb type (binary format) enforce strict key uniqueness. PostgreSQL 15 and later introduced the WITH UNIQUE KEY clause to validate JSON documents during construction, making this constraint explicit.

Typical symptoms

  • Error when using json_object() or jsonb_object_agg() functions with duplicate keys
  • INSERT or UPDATE statements fail with "Non-unique keys in JSON object" when constructing JSON
  • SQL/JSON constructor functions (json_object, jsonb_objectagg_unique) reject your query
  • PostgreSQL 16 strict JSON aggregate functions fail with duplicate key violations

Common causes

  1. Using json_object() or jsonb_object() with duplicate key arguments (key names appearing more than once)
  2. Aggregating data into JSON with json_object_agg() where group values have identical keys
  3. Constructing JSON from multiple sources (subqueries, UNION results) without deduplicating keys
  4. Migrating from json type (which allowed duplicates) to jsonb or using PostgreSQL 15+ SQL/JSON functions (which enforce uniqueness)
  5. Using json_object_agg_unique() or jsonb_object_agg_unique() in PostgreSQL 16+ when keys are not actually unique

How to fix "Non-unique keys in JSON object"

1Identify duplicate keys in your JSON construction

Review the function call or JSON construction to find which keys appear multiple times. For json_object(), check your argument list:

sql
-- This FAILS - "name" appears twice
SELECT json_object(
  'name', 'Alice',
  'age', 30,
  'name', 'Bob'  -- duplicate key
);

For aggregations, examine the source data:

sql
-- This FAILS - duplicate keys from subquery
SELECT json_object_agg(key, value)
FROM (
  SELECT 'id' as key, '1' as value
  UNION ALL
  SELECT 'id', '2'  -- same key again
) data;
2Ensure all keys are unique in json_object() calls

When constructing JSON with json_object() or jsonb_object(), each key must appear only once:

sql
-- CORRECT - all keys unique
SELECT json_object(
  'name', 'Alice',
  'age', 30,
  'email', 'alice@example.com'
);

-- If you need multiple values, use arrays or nested objects
SELECT json_object(
  'name', 'Alice',
  'age', 30,
  'aliases', json_array('Ali', 'Alicia')  -- use array for multiple values
);
3Deduplicate keys in json_object_agg() queries

When using json_object_agg() or json_object_agg_unique(), ensure the source data has unique keys per group:

sql
-- FAILS - multiple rows per group with same key
SELECT user_id, json_object_agg(key, value)
FROM user_metadata
GROUP BY user_id;

-- CORRECT - use DISTINCT or filtering to ensure one key per row
SELECT user_id, json_object_agg(key, value)
FROM (
  SELECT DISTINCT ON (user_id, key) user_id, key, value
  FROM user_metadata
  ORDER BY user_id, key, created_at DESC
) dedup
GROUP BY user_id;

-- Or use conditional aggregation to pick one value
SELECT user_id, json_object_agg(
  key,
  (array_agg(value ORDER BY created_at DESC))[1]  -- take newest
)
FROM user_metadata
GROUP BY user_id;
4Use UNION/UNION ALL carefully in JSON construction

When building JSON from multiple sources, deduplicate key names across queries:

sql
-- FAILS - both queries produce "status" key
SELECT json_object_agg(key, value)
FROM (
  SELECT 'status' as key, 'active' as value
  UNION ALL
  SELECT 'status', 'verified'  -- duplicate
) data;

-- CORRECT - prefix or distinguish keys
SELECT json_object_agg(key, value)
FROM (
  SELECT 'account_status' as key, 'active' as value
  UNION ALL
  SELECT 'verification_status', 'verified'
) data;
5Use jsonb when you need automatic deduplication

When migrating from json to jsonb, note that jsonb keeps only the last value for duplicate keys (no error thrown):

sql
-- json type: keeps both values (but may cause issues with strict functions)
SELECT '{"name": "Alice", "name": "Bob"}'::json;
-- Result: {"name": "Alice", "name": "Bob"}

-- jsonb type: keeps only last value (automatic deduplication)
SELECT '{"name": "Alice", "name": "Bob"}'::jsonb;
-- Result: {"name": "Bob"}

-- Use jsonb_object() for safe construction
SELECT jsonb_object(
  ARRAY['name', 'age'],
  ARRAY['Alice', '30']
);

Advanced notes

PostgreSQL 16 introduced stricter validation with json_object_agg_unique() and jsonb_object_agg_unique(), which enforce key uniqueness more aggressively. If you're seeing this error with these functions on PG16+, ensure your source data truly has unique keys per group.

The difference between json and jsonb matters here: json is a text representation that can technically hold duplicate keys (violating JSON spec), while jsonb is a binary format that normalizes keys and keeps only the last value. For new applications, prefer jsonb and the SQL/JSON functions (json_object, json_array) over the older json_object_agg functions.

When working with nested JSON or complex aggregations, consider using jsonb_set() or jsonb_insert() instead of constructors if you need conditional merging of objects, as these functions handle key conflicts by overwriting rather than rejecting.

In PostgreSQL 15+, you can use WITH UNIQUE KEYS in JSON constructors to make uniqueness requirements explicit: SELECT json('{"a":1}' FORMAT JSON ENCODING UTF8 WITH UNIQUE KEYS);

Frequently asked questions

What does "Non-unique keys in JSON object" mean?
In PostgreSQL, JSON objects are collections of key-value pairs where each key must be unique. When you use functions like json_object, jsonb_object_agg, or construct JSON with duplicate keys, PostgreSQL raises an error to prevent invalid JSON structures. The behavior differs slightly depending on the JSON type you use.
How do I fix "Non-unique keys in JSON object"?
PostgreSQL enforces unique keys in JSON objects, especially with jsonb and PostgreSQL 15+ SQL/JSON functions. This error occurs when you try to create or construct a JSON object with duplicate keys. Ensure all keys in your JSON objects are unique.
What causes "Non-unique keys in JSON object"?
Using json_object() or jsonb_object() with duplicate key arguments (key names appearing more than once) Aggregating data into JSON with json_object_agg() where group values have identical keys Constructing JSON from multiple sources (subqueries, UNION results) without deduplicating keys
Is the "Non-unique keys in JSON object" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading