Skip to main content
Multi-select fields (fields whose type is Multi-Select on a layout, stored internally as 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 as MULTI_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…UseNotes
Loop over each selection and do something with it (send a message per, create a record per)Repeat for Each pointed at the fieldSimplest option. No script needed.
Aggregate the selections into a single string, count, or other summary valueExecute ScriptCalculations can’t aggregate a multi-picklist directly.
Include the selections in a JSON body for an outbound API callExecute ScriptJSON InputBuild 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 layoutNot currently possibleSee 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 at input.parameters.<parameterName> is an array where each item is an object. The object’s properties are the ones you expose in the Inputs panel:
input.parameters.tags = [
  { label: "High priority" },
  { label: "Needs review" }
];

input.parameters.addresses = [
  { id: "addr_123", title: "HQ", street: "1 Main St" },
  { id: "addr_456", title: "Warehouse", street: "500 Depot Rd" }
];
Because the value is a list, guard for the case where nothing is selected before iterating. The ?? [] pattern is safe whether the input arrives as null, missing, or already empty:
const items = input.parameters.tags ?? [];

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 through input.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 label in 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 locked label behavior), 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:
InputPurpose
Select FieldChoose which property on the underlying source object to expose.
ParameterThe JavaScript property name used inside input.parameters.<parameterName>[i].<Parameter>. Rename freely — you’re not stuck with the source field’s name.
Test valueSandbox value used when clicking Execute in the script editor. Doesn’t affect production runs.
Only the properties you expose here are available to the script. If a script needs an additional field from the source object later, come back to the Inputs panel and add it — the Output Schema regenerates when you next click Execute.

Iterating each selection

Loop over the array and reach into whichever property you exposed. For a static multi-select, that property is always label:
const labels = (input.parameters.tags ?? []).map(tag => tag.label);

return { labels };
For a data-source-backed multi-select, use the Parameter name you configured for each field:
const { addresses } = input.parameters;

const streetLines = (addresses ?? [])
  .map(a => `${a.title}: ${a.street}`)
  .join('\n');

return { streetLines };
If you only need to act on each selection in a downstream action (create a record per, send an email per, and so on), skip the script entirely and use Repeat for Each directly on the field. Execute Script is the right choice when you need to transform the collection — aggregate, filter, reshape — before handing it off.

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:
const csv = (input.parameters.tags ?? [])
  .map(tag => tag.label)
  .join(', ');

return { csv };
Return 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:
const titles = (input.parameters.addresses ?? [])
  .map(a => a.title)
  .join(', ');

return { titles };

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.
const tags = (input.parameters.tags ?? []).map(tag => tag.label);

return {
  payload: JSON.stringify({
    ticketId: input.parameters.ticketId,
    tags
  })
};
Then map payload into the Send API Request action’s JSON Input field. On the wire the request body becomes:
{
  "ticketId": "T-1042",
  "tags": ["High priority", "Needs review"]
}
What the receiving API sees depends entirely on how you structure the object before stringifying. Common variants:
  • 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(', ') }
For the general 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, true on the first iteration.
  • Is Last Item — checkbox, true on the last iteration.
When to prefer Repeat for Each over Execute Script:
  • 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:
Invalid Type Error at line 1, position N: MULTI_PICKLIST
This applies everywhere calculations run — calculated columns on a Table, formulas on an Element layout, and the Run Calculation action. What to do instead. If your ultimate need is a text value derived from the selections (a comma-separated summary, a count, a joined description), do the work in Execute Script and, if the value needs to live on a record, write it back with Update Record Fields. If your need is per-selection processing, use Repeat for Each directly. For the full error catalog and the analogous Data Mine limitation, see Calculations troubleshooting → Multi-value and array-shaped values.