Power Automate: Copy SharePoint Multi-Person Fields Using Claims

Copying data between SharePoint lists usually behaves as expected. Text, numbers, and choice fields rarely cause problems.

Person fields are one of the exceptions.

I ran into this while building a Power Automate flow that created items in a destination list whenever a new item was added to a source list. Most fields copied without issue. The multi-person field did not.

The flow ran without errors, but the SharePoint multi-person column remained empty in the destination list.

Scenario Overview

The source list had a multi-person column. The destination list had a matching field. The requirement was to copy users from one list to another.

I tried the obvious approaches first. E-mail address. Display name. User ID. Direct field mapping. I tried passing individual properties from the person object in every combination I could think of. None of them worked. The flow succeeded every time, but the user column was always blank.

To make things harder, the source list included guest accounts that had no presence on the destination site. Those users never copied over regardless of what I tried, and I could not tell whether that was a separate problem or the same one.

It turned out the issue had nothing to do with the flow. It was how SharePoint represents people internally.

Why SharePoint Uses Claims

A person field in SharePoint is not a string value. It is a structured identity object. Power Automate exposes it like this:

{
  "Claims": "i:0#.f|membership|john.smith@example.com",
  "DisplayName": "John Smith",
  "Email": "john.smith@example.com",
  "Department": "Operations",
  "JobTitle": "Project Manager"
}

E-mail and display name are just attributes. SharePoint uses Claims when writing person fields.

Claims exists because e-mail and display name can both change over time, and users can exist in multiple contexts, including guest, synced, and external accounts. Claims is the stable identity reference SharePoint uses internally, so it is what SharePoint requires at write time.

When you pass an e-mail address instead of a Claims string, SharePoint does not attempt to resolve it to a user. The person column stays empty and no error is thrown. Display name behaves the same way. It is not unique and SharePoint does not use it as a lookup key. This is why the flow appears to succeed while the field does not populate.

NOTE: The guest account issue turned out to be a separate problem entirely, unrelated to Claims format. That is covered in the Troubleshooting section below.

What Claims Looks Like

Claims follow this format:

i:0#.f|membership|john.smith@example.com

For standard Microsoft 365 users, the prefix is always i:0#.f|membership|. Guest users follow a different pattern.

Single-person field:

{
  "Claims": "i:0#.f|membership|john.smith@example.com"
}

Multi-person field:

[
  {
    "Claims": "i:0#.f|membership|john.smith@example.com"
  },
  {
    "Claims": "i:0#.f|membership|jane.doe@example.com"
  }
]

Same structure. Single-person expects an object; multi-person expects an array of objects.

Building the Flow

Each user object in the source field already contains the Claims value. The solution is to extract it and rebuild the field structure correctly.

Step 1: Initialize an Array Variable

Before the loop, add an Initialize variable action in your flow. Set the type to Array and the initial value to []. This variable will hold the Claims objects before they are written to the destination list.

Step 2: Loop Through the Source Field

Add an Apply to each action using the multi-person column as input.

Step 3: Append Claims to the Array

Inside the loop, use Append to array variable with this value:

{
  "Claims": "@{items('Apply_to_each')?['Claims']}"
}

Step 4: Write to SharePoint

Pass the array into the destination multi-person field in Create item or Update item. SharePoint resolves the Claims values and populates the field.

The resulting array passed to SharePoint looks like this:

[
  {
    "Claims": "i:0#.f|membership|john.smith@example.com"
  },
  {
    "Claims": "i:0#.f|membership|jane.doe@example.com"
  }
]

NOTE: If Claims is null or missing on the source item, the append step will produce incomplete objects. See the Troubleshooting section for how to handle that.

Single vs. Multi-Person Fields

Both field types use the same underlying Claims structure. The difference is only in what SharePoint expects at write time:

In practice, normalizing everything into an array during processing keeps flows consistent and avoids special cases. If you later change a column from single to multi-person, the flow does not need to change.

Troubleshooting

The following issues came up while testing and troubleshooting person field updates.

The Flow Succeeds but the Person Column Is Still Blank

This is the most common symptom. It means SharePoint accepted the request but could not resolve the identity. Check that you are passing Claims and not e-mail or display name. Inspect the raw trigger output in the flow run history to confirm the Claims value is present on the source item.

Claims Is Null or Missing in the Source Field

This can happen if the source item was created programmatically, imported, or migrated in a way that did not properly resolve users. Open the item in SharePoint, re-save it manually, and check whether Claims populates on the next flow run.

If the source data is coming from outside SharePoint, you can construct the Claims string by prepending i:0#.f|membership| to the user’s e-mail address. Keep in mind that this only works if the user already exists in the destination site’s user store. If they have never accessed the site, SharePoint will not be able to resolve them even with a correctly formatted Claims string. In that case, the user needs to be provisioned at the destination first.

Guest Users Use a Different Claims Format

Guest accounts use a different Claims format:

i:0#.f|membership|john.smith_example.org#ext#@yourtenant.onmicrosoft.com

In this example, example.org represents the guest’s home organization and yourtenant.onmicrosoft.com is your tenant. The @ in the guest’s original e-mail address is replaced with an underscore, and #ext# marks the account as an external user.

If your list includes guest users, check the actual Claims value in the trigger output rather than assuming the standard format. The structure is the same. Only the string differs.

Guest Users Cannot Be Added to the Destination Site

This was the issue I ultimately encountered.

Guest users are provisioned in SharePoint’s user store only for site collections they have been granted access to. If the destination site is internal-only and the guest has never been provisioned there, SharePoint has no record of them to resolve the Claims string against.

The flow will succeed, but that user will not appear in the destination field.

The only way to resolve this is to grant the guest access to the destination site so SharePoint provisions the account there. If that is not an option, the person field cannot be populated for that user.

A practical fallback is storing guest display names or e-mail addresses in a separate text column so the information is not lost.

The Field Saves One User but Not Multiple

You are likely passing an object instead of an array. Multi-person fields require an array even when there is only one user.

Normalize all output to an array before writing to SharePoint.

Cross-Site or Cross-Tenant Copying Fails

Claims values are tenant-scoped. A Claims string from one tenant will not resolve in another.

If you are copying users across tenants, look up the user in the destination tenant and retrieve the destination Claims value before writing to SharePoint.

Summary

Once you understand that SharePoint requires Claims rather than e-mail or display name, the path forward is clear: extract Claims from the source field, build the array, and pass it back to SharePoint. For cases where Claims resolution is not possible, such as guest users copying to internal-only sites or cross-tenant scenarios, the limitation is identity access rather than the flow itself.