PostgreSQL requires all sub-arrays in a multidimensional array to have the same number of elements. This error occurs when you attempt to create a "ragged" array with inconsistent dimensions, violating PostgreSQL's rectilinear array structure requirement.
PostgreSQL enforces strict dimensional consistency for multidimensional arrays. By design, an array must be a rectilinear N-dimensional set of "cells" with no ragged edges. When you try to create an array where sub-arrays have different lengths, PostgreSQL rejects it because it cannot maintain the rectangular structure. This is a fundamental constraint that ensures array data integrity and consistent indexing behavior. The error typically occurs when parsing array literals with mismatched sub-array dimensions, either during INSERT statements, UPDATE operations, or when using array constructors in queries.
Review the array literal you're attempting to insert. Check that all sub-arrays at the same level have identical element counts.
Invalid example:
INSERT INTO table_name (array_col) VALUES ('{{a, b}, {c}}');
-- ERROR: First sub-array has 2 elements, second has 1Valid example:
INSERT INTO table_name (array_col) VALUES ('{{a, b}, {c, d}}');
-- Both sub-arrays have 2 elementsWhen inserting multiple rows with array values, verify each row has arrays with identical dimensions:
INSERT INTO table_name (array_col) VALUES
('{{1, 2}, {3, 4}}'), -- 2x2 array
('{{5, 6}, {7, 8}}'), -- 2x2 array - MATCHES
('{{9, 10}, {11}}'); -- ERROR: Second row is raggedIf you have data with naturally varying lengths, pad the shorter sub-arrays with NULL to maintain rectangular structure:
-- Invalid (ragged):
INSERT INTO meetings (schedule) VALUES ('{{meeting, lunch}, {meeting}}');
-- Valid (padded with NULL):
INSERT INTO meetings (schedule) VALUES ('{{meeting, lunch}, {meeting, NULL}}');If you truly need arrays of varying lengths, instead of a multidimensional array, create an array of a custom DOMAIN type:
-- Define a domain for a single activity record
CREATE DOMAIN activity_record AS TEXT[];
-- Create a table with an array of variable-length activity records
CREATE TABLE schedule (
id SERIAL PRIMARY KEY,
activities activity_record[] -- Array of variable-length arrays
);
INSERT INTO schedule (activities) VALUES
(ARRAY[ARRAY['meeting', 'lunch'], ARRAY['meeting']]::activity_record[]);This allows each element to be an array of different lengths without violating dimensional consistency.
Add pre-insertion validation in your application layer to catch dimension mismatches early:
// Example validation function
function validateMultidimensionalArray(arr) {
if (!Array.isArray(arr) || arr.length === 0) return true;
if (Array.isArray(arr[0])) {
const firstLen = arr[0].length;
return arr.every(subArr =>
Array.isArray(subArr) && subArr.length === firstLen
);
}
return true;
}
const data = [[1, 2], [3, 4]]; // Valid
const badData = [[1, 2], [3]]; // Invalid
if (!validateMultidimensionalArray(badData)) {
throw new Error('Array dimensions do not match');
}PostgreSQL arrays are strongly typed and dimensional. When you declare a column as int[][], PostgreSQL expects a 2D array where every row has the same number of columns. This differs from languages like Python or JavaScript that support ragged (jagged) arrays by default.
Array dimension vs. bounds: PostgreSQL tracks array bounds (dimensions) separately from the data type. You can specify bounds explicitly: CREATE TABLE t (x int[1:2][1:3]) declares a 2x3 array with bounds starting at 1. If you provide data that violates these bounds, PostgreSQL will also reject it.
Performance consideration: Consistent array dimensions allow PostgreSQL to optimize storage and indexing. Ragged arrays would require variable-length indexing that impacts query performance.
NULL handling: PostgreSQL distinguishes between a NULL sub-array element and an array containing NULL values. Use NULL to pad arrays when matching dimensions: '{{{a, b}, {c, NULL}}}' is valid; '{{{a, b}, {c}}}' is not.
ERROR: syntax error at end of input
Syntax error at end of input in PostgreSQL
Bind message supplies N parameters but prepared statement requires M
Bind message supplies N parameters but prepared statement requires M in PostgreSQL
ERROR: value too long for type character varying
Value too long for type character varying
insufficient columns in unique constraint for partition key
How to fix "insufficient columns in unique constraint for partition key" in PostgreSQL
ERROR 42501: must be owner of table
How to fix "must be owner of table" in PostgreSQL