The #CALC! error with the message “Nested arrays are not supported” occurs when an Excel formula attempts to create an array inside another array. Excel’s dynamic array grid can output one-dimensional vectors and two-dimensional tables, but it cannot store an array within an individual cell of another array. When array-iteration functions like MAP, BYROW, BYCOL, or SCAN contain a LAMBDA that returns multiple values per step rather than a single scalar value, calculation halts and displays #CALC!.
Quick Fix
Ensure the inner
LAMBDAfunction evaluates to a single scalar value for every step. If usingMAPorBYROWwith a function that outputs multiple cells (likeFILTER,TEXTSPLIT, orUNIQUE), wrap that function in an aggregator likeTEXTJOIN,CONCAT,SUM, orINDEX(..., 1). To combine multiple variable-length arrays row-by-row, use a recursiveREDUCEandVSTACKpattern instead.
Why Excel Prohibits Nested Arrays
In traditional programming languages, a list can easily contain other lists (e.g., [1, [2, 3], 4]). In Excel, however, every dynamic array must resolve directly to physical worksheet coordinates:
┌────────────────────────────────────────────────────────┐
│ EXCEL WORKSHEET GRID PARADIGM │
│ • A dynamic array is a flat 2D matrix (Rows x Cols) │
│ • Each grid coordinate (Cell) must hold ONE value │
└───────────────────────────┬────────────────────────────┘
│
EVALUATING: MAP or BYROW
│
┌───────────────────────────▼────────────────────────────┐
│ Iteration 1: Returns 1 value ──► Allowed │
│ Iteration 2: Returns 3 values ──► Array within array │
│ │
│ RESULT: Grid cannot draw nested sub-tables ──► #CALC! │
└────────────────────────────────────────────────────────┘
Because an individual coordinate cannot expand into a secondary independent grid, Excel’s calculation engine rejects any formula that produces arrays of arrays, as outlined in Troubleshooting #SPILL! and #CALC! Errors: The Dynamic Array Diagnostic Guide.
Primary Scenarios That Trigger the Error
1. Calling Multi-Value Functions Inside MAP, BYROW, or BYCOL
The helper functions MAP, BYROW, and BYCOL are designed to step through an input array and return an output array of identical or aggregated dimensions. The LAMBDA supplied to these functions must return a single scalar value for every loop.
The Problem:
Splitting text across multiple rows inside MAP:
=MAP(A2:A10, LAMBDA(cell, TEXTSPLIT(cell, ","))) <-- Triggers #CALC!
TEXTSPLIT returns an array of text pieces. Because MAP is already iterating through an array, asking MAP to store an array of text pieces inside each item of its parent array attempts to create a nested array, failing immediately with #CALC!.
Similarly, running a multi-result FILTER inside BYROW:
=BYROW(DeptList, LAMBDA(d, FILTER(Employees[Name], Employees[Dept]=d))) <-- Triggers #CALC!
If a department has five employees, FILTER returns five rows. BYROW cannot place five rows into a single row’s slot.
2. Literal Nested Arrays
Manually constructing nested array constants triggers an immediate calculation break:
={1, {2, 3}} <-- Triggers #CALC!
=MUNIT({1, 2}) <-- Triggers #CALC!
In =MUNIT({1, 2}), MUNIT creates an identity matrix for a given dimension. Passing {1, 2} asks Excel to construct a $1 \times 1$ matrix and a $2 \times 2$ matrix inside the same array, which is unsupported.
Solutions and Workarounds
Workaround 1: Aggregate to a Scalar Inside the Loop
If the objective is to display or summarize multiple values per item, condense the nested output into a single string or number before the LAMBDA returns:
- For Text Splitting or Extraction:
=MAP(A2:A10, LAMBDA(cell, TEXTJOIN(", ", TRUE, TEXTSPLIT(cell, ",")))) - For Filtered Lookups:
=BYROW(DeptList, LAMBDA(d, TEXTJOIN("; ", TRUE, FILTER(Employees[Name], Employees[Dept]=d, "None"))))
Because TEXTJOIN flattens the multi-cell result into a single text string, the parent MAP or BYROW function receives a valid scalar value.
Note: If using FILTER inside an aggregator, always define the third argument ([if_empty]) to prevent #CALC! empty-array errors from bubbling up, as detailed in #CALC! Error: Empty Array results in FILTER.
Workaround 2: Pick an Explicit Index
If you only need a specific element from the nested calculation, extract that single item using INDEX or CHOOSEROWS:
=MAP(DeptList, LAMBDA(d, INDEX(FILTER(Employees[Name], Employees[Dept]=d, "None"), 1)))
This restricts the output to exactly the first matching employee, keeping the output scalar.
Workaround 3: The REDUCE and VSTACK Stacking Pattern
When you need to process a list of items and genuinely output a stacked, multi-row table where each sub-calculation has variable length, replace MAP or BYROW with REDUCE paired with VSTACK:
=LET(
keys, A2:A5,
DROP(
REDUCE("", keys, LAMBDA(acc, k,
VSTACK(acc, FILTER(DataTable, DataTable[Category]=k, ""))
)),
1
)
)
How This Works:
REDUCEstarts with an initial blank accumulator ("").- On every loop, it runs
FILTERfor keyk(which returns multiple rows). VSTACKstacks the new rows underneath the accumulator, creating a single continuous two-dimensional table rather than nesting arrays inside cells.DROP(..., 1)strips away the initial blank seed row at the top.
To learn how LET optimizes variable execution in complex array stacking, see Using LET to define variables and reduce #NAME? errors.
If your formula structure requires self-referencing loops rather than standard array iterators, check the stack boundaries outlined in #CALC! in LAMBDA: Recursive call limits.