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.
Fixes ARRAY_SUBSCRIPT
INSERT INTO table_name (array_col) VALUES ('{{a, b}, {c}}');
-- ERROR: First sub-array has 2 elements, second has 1INSERT INTO table_name (array_col) VALUES ('{{a, b}, {c}}');-- ERROR: First sub-array has 2 elements, second has 1Multidimensional arrays must have sub-arrays with matching dimensions
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.