A Notion rollup aggregating a multi-select property with “Show original” returns a list<list<string>>—a nested collection object—not a plain string.
To convert this into readable, filterable text, you must chain three Formula 2.0 array methods using modern dot notation:
JavaScript
prop("Expertise Rollup").flat().unique().join(", ")
The .flat() method collapses the nested list-of-lists into a single flat array. The .unique() method removes duplicate tags that appear across multiple related pages. Finally, .join(", ") serializes the array into a clean, comma-separated text string that downstream formulas and filters can read.
Prerequisites
- Notion Formula 2.0: Your workspace must be using the modern Formula 2.0 engine. If you are on a legacy layout, array methods like
.flat()and.unique()will not execute. - “Show original” Aggregation: This formula specifically handles rollups set to “Show original”. If your rollup is set to “Show unique values”, Notion pre-flattens it into a
list<string>, meaning you only needprop("Rollup").join(", ").
The Syntax Breakdown
prop("Expertise Rollup")— Retrieves the raw rollup value. When targeting a multi-select property, this outputs a nested array:[["SEO", "Copywriting"], ["Design"]]..flat()— Strips away the inner array brackets, combining all child lists into one continuous list:["SEO", "Copywriting", "Design"]. Empty sub-lists are safely ignored..unique()— Scans the flattened list and removes duplicates using case-sensitive comparison. Without this, a tag like “Copywriting” present on multiple related pages would repeat multiple times in your final text..join(", ")— Converts the final array into a singletextdata type, inserting a comma and space between each item. The result is pure, filterable text.
Real-World Example: Cross-Database Freelancer Expertise
A content operations manager maintains a “Campaigns” database related to a “Freelancers” database. Each freelancer has a multi-select property for their specific skills.
The manager creates an “Expertise Rollup” to surface team skill coverage for a given campaign. However, when she tries to filter the dashboard using contains(prop("Expertise Rollup"), "SEO"), it silently fails because .contains() cannot read nested arrays.
Raw Data Table (Rollup Output)
| Campaign | Related Freelancers | Expertise Rollup (Raw Output) |
| Q3 Launch | Maya Chen, Dev Patel | [["SEO", "Copywriting"], ["Motion", "Design"]] |
| Brand Refresh | Dev Patel, Sara Kim | [["Motion", "Design"], ["Copywriting", "Social"]] |
| SEO Sprint | Maya Chen, Sara Kim | [["SEO", "Copywriting"], ["Copywriting", "Social"]] |
The Formula Applied
The manager adds a new formula property named “Team Expertise” to process the raw rollup:
JavaScript
prop("Expertise Rollup").flat().unique().join(", ")
Output Table
| Campaign | Team Expertise (Clean String) |
| Q3 Launch | SEO, Copywriting, Motion, Design |
| Brand Refresh | Motion, Design, Copywriting, Social |
| SEO Sprint | SEO, Copywriting, Social |
Because the output is now a standard text string, the manager’s .contains() filter logic now works flawlessly.
Common Related Errors & Fixes
.format()Wraps Output in Brackets -> Cause: You tried to force the conversion usingprop("Rollup").format(). In Formula 2.0,format()serializes the exact data structure, literally printing the nested array brackets as text. -> Fix: Remove.format()and use the.flat().join(", ")pipeline to extract the text cleanly.- Formula Cannot Find
.flat()-> Cause: You typedflatten(), which is a common JavaScript method, but Notion strictly uses.flat(). -> Fix: Change the syntax to.flat(). .contains()Returns False Negatives -> Cause: You are running a text search function directly against an array object. The function fails silently instead of throwing a visible error. -> Fix: Serialize the rollup into a string first using.join(), or check the array directly usingprop("Rollup").flat().includes("SEO").
Key Takeaways
- Rollups targeting multi-select properties return a nested
list<list<string>>, which breaks standard text formulas. - The
.flat().unique().join(", ")pipeline is the safest and most reliable way to serialize multi-select rollups into clean text. - Using Formula 2.0’s dot notation allows you to chain array methods elegantly without getting lost in nested parentheses.
Frequently Asked Questions
Can I check if a tag exists without joining it into a string?
Yes. If you only need to return a true/false checkbox (e.g., “Does anyone on this campaign know SEO?”), you can skip .join(). Use prop("Expertise Rollup").flat().includes("SEO"). The .includes() method natively searches lists.
What happens if a related page has zero multi-select tags?
If a related page has an empty multi-select field, it contributes an empty sub-list [] to the rollup. When .flat() processes the array, it safely drops those empty items. It will not insert null values or stray commas into your final string.
Does this work in older Notion workspaces using Formula 1.0?
No. Formula 1.0 does not support array methods, list data types, or dot notation. If you are somehow still on Formula 1.0, you must click into the formula editor and accept the prompt to migrate your workspace to the modern engine.