Live training: next batches coming soon. Join the waitlist:Waitlists open:Developer Training →Developer →Copilot Studio Training →Copilot Studio →

How to Update a Row in Dataverse Using Power Automate (Update, Upsert and Lookups)

Many older guides say the Dataverse Update a row action quietly creates a new row when the Row ID doesn’t exist. That may have been true once, but when I tested it this week, the action stopped with a 404 Does Not Exist error.

So here’s the better way to update a row in Dataverse from Power Automate: use Update a row with the row’s GUID in Row ID. When the row might not exist yet, switch to Upsert a row instead.

In this tutorial, we’ll build a power automate update a row dataverse flow step by step. You’ll see where the Row ID comes from, how to update every row that matches a filter, and how Upsert a row behaves.

We’ll also set lookup and choice columns, and look at the real errors I hit along the way.

The Sample Table We’ll Use

Every example uses one table in my Power Platform developer environment. If you’re new to tables and environments, start with what Microsoft Dataverse is.

ColumnLogical nameType
Subjectcr85a_subjectText (primary column)
Request Numbercr85a_requestnumberText
Statuscr85a_statusChoice: Open 770700000, In Progress 770700001, Closed 770700002
Customercr85a_customerLookup to Customers (required)
Descriptioncr85a_descriptionText
Request Categorycr85a_requestcategoryFormula (read-only)

The table is Service Requests, with entity set name cr85a_servicerequests. The cr85a_ part is my publisher prefix, so your column names will start with your own prefix.

Before the run it held six requests, like Network Issue (REQ-1006, In Progress) and Monitor Flicker (REQ-1009, Open).

Build the Flow Step by Step

Here’s the beginner path I used. Dataverse actions are Premium, so you need a license that covers premium connectors.

  1. Go to make.powerautomate.com and pick the environment that holds your table (top right).
  2. Select Create > Instant cloud flow, choose Manually trigger a flow and select Create.
  3. Select + > Add an action, search Dataverse and select See more.
  4. Pick Update a row (or Upsert a row), choose the Table name and fill in the fields.
  5. Select Save, then Test > Manually > Run flow. Open the run and click each action to see its output.
Add an action pane in Power Automate listing Microsoft Dataverse Update a row and Upsert a row actions

For more flow basics, browse our Power Automate tutorials hub.

Method 1: Update a Row With the ID From an Earlier Step (Recommended)

Use this when an earlier step already knows the row. In my demo, the flow first ran Add a new row to add data to a Dataverse table (Printer Jam, REQ-1007), then updated that same row.

In Update a row, set Table name to Service Requests. Click Row ID and pick the Service Request token from Add a new row. That token is the table’s unique identifier (GUID).

Update a row action with Row ID set to the Service Request dynamic content token

Next, open Advanced parameters and show only the columns you want to change. I picked Description and Status.

Update a row advanced parameters with Description and Status 770700001 filled in

Here’s the key part of the action’s Code view:

"operationId": "UpdateOnlyRecord",
"parameters": {
  "entityName": "cr85a_servicerequests",
  "recordId": "@outputs('Add_a_new_row')?['body/cr85a_servicerequestid']",
  "item/cr85a_status": 770700001,
  "item/cr85a_description": "Alice replaced the fuser on 10/20/2026. Testing color jobs now."
}

To check the result, I added a Compose action named Updated status:

@outputs('Update_a_row')?['body/cr85a_status@OData.Community.Display.V1.FormattedValue']

The run showed In Progress, so the status changed on the new row.

Flow run showing the Updated status Compose output In Progress

How does this work?

Update a row changes only the columns you fill in. Microsoft’s docs say blank fields are skipped unless you pass a null on purpose, so Subject and Customer stayed as they were.

The action also returns the full row, which is why the Compose can read the status label right away.

The Row ID can come from other places too:

  • Dataverse trigger (When a row is added, modified or deleted): triggerOutputs()?['body/cr85a_servicerequestid']
  • First row of a List rows step: first(outputs('List_rows')?['body/value'])?['cr85a_servicerequestid']
  • Add a new row: the Service Request token, as above.

Method 2: Update Every Row That Matches a Filter

Update a row changes one row per call. To change several, list the rows first and loop over them.

In List rows, set Filter rows to an OData filter. In my run, cr85a_status eq 770700000 returned 3 Open requests, the same check I use to count rows from a Dataverse table.

Then add Apply to each over the List rows value, and put Update a row inside it. Here’s the Row ID expression:

items('Apply_to_each')?['cr85a_servicerequestid']

How does this work?

items() returns the current row of the loop, and cr85a_servicerequestid is its GUID. If your loop has another name, use that name with underscores instead of spaces.

So here’s the catch: List rows returns up to 5,000 rows by default, and each update is one more action run. Filter as tightly as you can.

Method 3: Upsert a Row When It Might Not Exist

Use Upsert a row when you don’t know if the row is already there, like a nightly sync or when you import CSV data into Dataverse. If the Row ID exists, it updates. If not, it creates the row with that GUID.

I gave it a brand-new GUID, 5c0d2b7e-1a2b-4c3d-8e9f-202610200001, plus Subject Projector Setup, REQ-1008, Status Open and Priority Low.

My first run failed with this message:

Upsert a row BadRequest error Enter Customer details in the flow run

Customer is required on this table, and a create needs every required column. So I added the Customer lookup and ran it again.

Upsert a row action with a new Row ID GUID and the Customer lookup value
"parameters": {
  "entityName": "cr85a_servicerequests",
  "recordId": "5c0d2b7e-1a2b-4c3d-8e9f-202610200001",
  "item/cr85a_subject": "Projector Setup",
  "item/cr85a_requestnumber": "REQ-1008",
  "item/cr85a_status": 770700000,
  "item/cr85a_priority": 770700000,
  "item/cr85a_Customer@odata.bind": "cr85a_customer1s(<customer-row-guid>)"
}

The second run succeeded and created Projector Setup with exactly that GUID.

Upserted row Compose output showing Projector Setup and its new GUID

How does this work?

Upsert a row checks the GUID first. Because no row had it, Dataverse ran a create, so all create rules applied, including required columns and the table’s business logic.

Microsoft’s docs describe the other half: when the row already exists, upsert runs an update instead of adding a duplicate.

What About Alternate Keys?

Microsoft’s Dataverse docs say upsert is mostly used with alternate keys in data integration, when the other system doesn’t store Dataverse GUIDs. You create one in Power Apps under the table’s Keys > New key.

The Web API then addresses a row by key, like example_records(example_key1=2,example_key2=2). The connector’s Row ID, though, is documented as a GUID, and I didn’t test key syntax there.

Pro Tip: If you only have a business key like REQ-1008, use List rows with cr85a_requestnumber eq 'REQ-1008', then update the GUID it returns. A new key also isn’t usable right away, since a system job builds its index first.

How to Update a Dataverse Lookup Column

A lookup needs the related table’s entity set name plus the row GUID: <entity set name>(<guid>). The designer shows the field as Customer (Customers).

cr85a_customer1s(87309834-e89b-48b4-8ccd-f4d8d5d5b19d)

How does this work?

cr85a_customer1s is the entity set of my Customers table, not its display name. To find yours, go to make.powerapps.com > Tables, open the table and select Tools > Copy set name. You set this up when you create a table in Dataverse.

I tested this format in Add a new row and Upsert a row, and Microsoft documents the same format for Update a row.

Set a Choice Column by Number

The designer shows Status as a dropdown with labels, but the flow stores the number. When you set it with an expression, the box shows a custom value like 770700001.

An out-of-range number fails. My test with 999 returned “The value 999 of ‘cr85a_status’ … is outside the valid range.” Filters need the number too, which I cover when I get the choice column value.

Update a Row vs Upsert a Row: Which One Should You Use?

I sent Update a row a GUID that doesn’t exist (00000000-0000-0000-0000-000000000002). It returned 404 NotFound with “Does Not Exist” and created nothing.

Update a row test with a missing GUID returning statusCode 404
Update a rowUpsert a row
Operation IDUpdateOnlyRecordUpdateRecord
Row existsUpdates itUpdates it
Row missing404 Does Not ExistCreates it with that GUID
Required columnsOnly the ones you changeAll required columns, in case it creates
Best forRows you just read or createdSyncs and imports

If you need the row’s values before you change them, get a row by ID from Dataverse first.

Things to Keep in Mind

  • Formula columns don’t show up in Update a row. When I forced Request Category into the definition, the save failed with “does not contain a definition for parameter”. Fix: change the source columns instead.
  • Row ID must be a GUID. A request number like REQ-1006 in Row ID gives a BadRequest. Fix: look up the GUID with List rows first.
  • Upsert can create rows, so it needs required columns. Fix: pass them every time, not just on the first run.
  • Choice values are numbers. Fix: copy them from the column’s choice list, like 770700001 for In Progress.

If you build flows like this at work, our Power Automate training course covers Dataverse flows on real projects.

Want more Dataverse flows? These pair well with this one:

Frequently Asked Questions

How do I update a row in Dataverse using Power Automate?

Add the Microsoft Dataverse Update a row action, pick the Table name, and put the row’s GUID in Row ID, usually from a trigger, Add a new row or List rows. Then fill only the columns you want to change.

What’s the difference between Update a row and Upsert a row?

Update a row only changes an existing row and returns a 404 error when the GUID doesn’t exist. Upsert a row updates the row if it exists and creates it with that GUID if it doesn’t.

Can I use an alternate key with Upsert a row?

Alternate keys are how Dataverse usually identifies rows for upsert in integrations, through the Web API. The connector’s Row ID is documented as a GUID, so in a flow, find the GUID with List rows first. See Microsoft Learn on Dataverse upsert.

How do I update a Dataverse lookup column in Power Automate?

Enter the related table’s entity set name and the row GUID, like cr85a_customer1s(guid). Get the set name in Power Apps from the table’s Tools menu with Copy set name. Details: Use a flow to update a row in Dataverse.

Why don’t I see my formula column in Update a row?

Formula and other calculated columns are read-only, so the action doesn’t list them. Update the columns the formula uses and Dataverse recalculates the value.