#CALC! Error: Nested Array limitations

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 LAMBDA function evaluates to a single scalar value for every step. If using MAP or BYROW with a function that outputs multiple cells (like FILTER, TEXTSPLIT, or UNIQUE), wrap that function in an aggregator like TEXTJOIN, CONCAT, SUM, or INDEX(..., 1). To combine multiple variable-length arrays row-by-row, use a recursive REDUCE and VSTACK pattern 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:

  1. REDUCE starts with an initial blank accumulator ("").
  2. On every loop, it runs FILTER for key k (which returns multiple rows).
  3. VSTACK stacks the new rows underneath the accumulator, creating a single continuous two-dimensional table rather than nesting arrays inside cells.
  4. 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.