MULTI_PICKLIST) hold several selected options in a single value. That shape works cleanly on the record itself, but it behaves differently in each place you might reference it downstream — calculations, an Execute Script action, a Repeat for Each loop, or a Send API Request body. This page names the shape, says which action to pick for each need, and gives the working pattern.
If you’re here because of the specific error Invalid Type Error at line 1, position N: MULTI_PICKLIST, jump to In calculations.
The two shapes you’ll encounter
Multi-picklist fields. A field configured as Multi-Select on an Element or Table layout. A single cell holds several selected options. Elementum stores the underlying type asMULTI_PICKLIST.
Multi-value text from Data Mine. When a Data Mine trigger fires, a multi-value text column in the payload serializes as an array of objects like [{"value":"WD","type":"TEXT"}, ...] rather than plain text. This is a different problem from a multi-picklist field — it’s a text or JSON payload whose value happens to be array-shaped. See Flattening a Data Mine array payload into plain text for the specifics; the rest of this page is about multi-picklist fields on a record.
Which action to use
Pick the action that matches what you’re trying to do with the selections. Every row below has a working pattern later on this page.| I want to… | Use | Notes |
|---|---|---|
| Loop over each selection and do something with it (send a message per, create a record per) | Repeat for Each pointed at the field | Simplest option. No script needed. |
| Aggregate the selections into a single string, count, or other summary value | Execute Script | Calculations can’t aggregate a multi-picklist directly. |
| Include the selections in a JSON body for an outbound API call | Execute Script → JSON Input | Build the payload in a script, then pass the stringified result into the Send API Request action. |
| Produce a delimited string inside a calculated column on a Table or a formula on an Element layout | Not currently possible | See In calculations. Do the work in Execute Script and write the result back to a field. |
In Execute Script
Multi-select inputs come through as an array of objects with named properties, not an array of primitive strings. What the object exposes depends on how the multi-select field is configured — a static option list and a data-source-backed multi-select map into the Inputs panel differently.The runtime shape
Given a multi-select field mapped as an input parameter, the value atinput.parameters.<parameterName> is an array where each item is an object. The object’s properties are the ones you expose in the Inputs panel:
?? [] pattern is safe whether the input arrives as null, missing, or already empty:
Configuring the input mapping
Every multi-select input in the Script Configuration → Inputs panel starts with a Parameter name — that’s the JavaScript variable you’ll reference throughinput.parameters.<parameterName>. The rows nested underneath control which properties of each selected item are exposed inside the script.
Two behaviors, depending on how the source field is configured:
- Static option list. The Inputs panel shows one locked row with
labelin both Select Field and Parameter. No + Add Field control. Each item in the resulting array has exactly one property —label. This applies to static single-select fields too (with the same lockedlabelbehavior), but the value comes through as an array only for multi-select. - Data-source-backed multi-select (options come from records of an Object, an API-powered dropdown, or a similar dynamic source). The Inputs panel shows a + Add Field control. Each field you add has three inputs:
| Input | Purpose |
|---|---|
| Select Field | Choose which property on the underlying source object to expose. |
| Parameter | The JavaScript property name used inside input.parameters.<parameterName>[i].<Parameter>. Rename freely — you’re not stuck with the source field’s name. |
| Test value | Sandbox value used when clicking Execute in the script editor. Doesn’t affect production runs. |
Iterating each selection
Loop over the array and reach into whichever property you exposed. For a static multi-select, that property is alwayslabel:
Aggregating into a comma-separated string
There is no calculation function that aggregates a multi-picklist into a delimited string (see In calculations). The working pattern is Execute Script:csv from the script and reference it in downstream actions — for example, mapping it into a text field with Update Record Fields, or into a message body in Post Comment or Send Email Notification.
For a data-source-backed multi-select, swap the .map(tag => tag.label) for whichever property you want to aggregate:
Passing multi-select values into a JSON API body
The JSON Input field on the Send API Request action expects a plain JSON string, not a structured object. Build the payload in Execute Script,JSON.stringify() it, and map the resulting string into JSON Input. This pattern decouples payload construction from the API action — you can swap the script’s inputs without touching the API step, and reuse the same body across several Send API Request actions.
payload into the Send API Request action’s JSON Input field. On the wire the request body becomes:
- JSON array of strings —
{ tags: (input.parameters.tags ?? []).map(t => t.label) } - JSON array of full objects —
{ tags: input.parameters.tags ?? [] }(each item keeps every property you exposed in the Inputs panel) - Comma-separated string —
{ tags: (input.parameters.tags ?? []).map(t => t.label).join(', ') }
JSON.stringify requirement on this action and the failed to convert input data to params error you’ll see if you skip it, see the Send API Request reference.
In Repeat for Each
The Repeat for Each action accepts a multi-picklist field directly as its Collection. You do not need to bridge through Execute Script or a Search Records action first. Inside the loop, each property you exposed on the selected item becomes a separate value reference in the picker (type$ in any inner action’s fields). For a static multi-select, that’s a single Label entry. For a data-source-backed multi-select, it’s one entry per exposed field, prefixed with the parameter name — Addresses - Title, Addresses - ID, and so on. Two loop-level helpers are always available:
- Is First Item — checkbox,
trueon the first iteration. - Is Last Item — checkbox,
trueon the last iteration.
- You want to run one action (or a small block of actions) per selection without transforming the collection.
- The per-selection logic is visible in the automation builder rather than tucked inside JavaScript — easier for reviewers and future maintainers to read.
- No aggregation is needed. If you need a totalled number or a joined string across selections, use Execute Script instead.
In calculations
There is no supported calculation pattern that aggregates a multi-picklist field into a delimited string, or otherwise operates on all of its selections at once.STRING_AGG and STRING_AGG_UNIQUE accept single-value text supplied through a related-field aggregation only, and passing a MULTI_PICKLIST field to either raises:
Related documentation
- Execute Script action — full reference for input mapping, Output Schema, and the runtime environment.
- Repeat for Each action — collection loops in the automation builder.
- Send API Request action — request body shapes, authorization, and the
JSON.stringifyrequirement. - Calculations troubleshooting — the multi-value and Data Mine array sections cover the calculation-side limitations in more depth.
- Data Mine — where the array-of-objects text payload shape comes from.