Tutorials/Power Apps/Silent Saves Exposed: 8 Ways Your Power Apps Patch Can Fail Without Errors
Power Appsintermediate

Silent Saves Exposed: 8 Ways Your Power Apps Patch Can Fail Without Errors

Your Patch formula runs without a red squiggle, but the data never arrives. These eight root causes—from stale references to delegation delusions—will help you find the culprit in minutes.

NA
Narmer Abader
@narmer · Published June 3, 2026

The moment you deploy a Power Apps solution and hear, “The data isn’t saving,” your first instinct is to look for red underlines in the formula bar. But there are none. The Patch function ran without throwing an error, yet the record never materialized—no new row, no update, no trace.

Eight causes regularly lead to this silent failure. In this article I’ll walk through each one using a common scenario: a bug-tracking app with a BugList table. You’ll see the mistake, the symptom, and the fix. Along the way you’ll pick up debugging patterns that catch these issues before they reach your users.

Your Scenario: A Bug-Tracking App

Imagine you have a SharePoint list (or Dataverse table) named BugList with these columns:

ColumnTypeNotes
TitleText (required)Bug name
SeverityChoice: Low, Medium, High, Critical
AssignedToLookup to UsersPerson assigned
StatusChoice: Open, In Progress, Resolved, Closed
EstimatedHoursNumberHours to fix
BugIDAuto‑numberPrimary identifier

Your app has a gallery (galBugs) that shows the current bugs, and a form panel for editing. The Selected item feeds into the update logic.

Many of the failures below stem from how you reference the record to patch. Let’s start with the most common.

Creating When You Meant to Edit

The single most frequent bug: you used Defaults(BugList) as the second argument when you intended to update an existing row.

powerfxAccidental create instead of update
Patch(BugList, Defaults(BugList), {
Title: txtTitle.Text,
Severity: { Value: "High" },
EstimatedHours: Value(txtHours.Text)
})

If the user’s intention was to save changes to the bug currently selected in the gallery, the code above adds a new row with only those three fields populated. The record you thought you were updating stays untouched.

How to spot: Count the rows in BugList before and after the operation. If the count increased by one, this is your bug.

Fix: Pass the actual record you want to modify.

powerfxPass the real record
Patch(BugList, galBugs.Selected, {
Title: txtTitle.Text,
EstimatedHours: Value(txtHours.Text)
})

Patch runs without a compile‑time error even when the record you’re trying to patch no longer exists—or points to a different row. This happens most often when you use galBugs.Selected in multiple Patch calls and the gallery requeries between them.

powerfxSecond call may target a different row
Patch(BugList, galBugs.Selected, { Status: { Value: "In Progress" } });
// ... gallery refreshes (e.g., after a filter change)
Patch(BugList, galBugs.Selected, { AssignedTo: varUser });

The second Patch might not hit the same record, or Selected might be blank.

How to spot: Manually re‑select the item before the second operation—if that fixes it, you have a stale reference.

Fix: Capture the record into a variable immediately after the user selects it, then use that variable for all subsequent patches.

powerfxStable record variable
Set(varCurrentBug, galBugs.Selected);
Patch(BugList, varCurrentBug, { Status: { Value: "In Progress" } });
Patch(BugList, varCurrentBug, { AssignedTo: varUser });

Silent Type Coercion That Drops Values

Power Fx tries to be friendly about types, but sometimes the data source refuses to accept a coerced value and silently discards it. A classic example is writing a Text property directly into a Number column.

powerfxString sent to number column
Patch(BugList, galBugs.Selected, { EstimatedHours: txtHours.Text })

txtHours.Text is a string. For a SharePoint list, this value may simply not be written—the rest of the patch succeeds, but EstimatedHours remains unchanged.

How to spot: Check the target column after the operation. If it stayed the same (or became blank), type coercion may be the cause.

Fix: Convert explicitly with Value() for numbers, DateValue() for dates, and Text() to force a string.

powerfxExplicit conversion
Patch(BugList, galBugs.Selected, { EstimatedHours: Value(txtHours.Text) })
Tip

Always apply conversion when the source of a value is a TextInput, Label, or any control that outputs text—even if the column appears to accept strings.

Lookup and Choice Columns Expect a Specific Shape

Lookup columns are not strings, and choice columns cannot be simple text unless the connector expects that shape. AssignedTo is a lookup to the Users table. Patching it with an email address will fail silently.

powerfxIncorrect lookup value
Patch(BugList, Defaults(BugList), { AssignedTo: "jane@contoso.com" })

How to spot: The AssignedTo field remains empty. If a required lookup is blank, the whole record may not save.

Fix for Dataverse / SharePoint lookups: Pass the related record obtained through LookUp.

powerfxCorrect lookup record
Patch(BugList, Defaults(BugList), {
AssignedTo: LookUp(Users, Email = "jane@contoso.com")
})

Fix for choice columns: Use the { Value: "…" } record shape. This applies to both SharePoint choices and Dataverse choices.

powerfxChoice column correct format
Patch(BugList, Defaults(BugList), { Severity: { Value: "High" } })

Missing Required Fields on Create

When you create a row with Defaults(BugList), every required column must be provided. If Title is required and you omit it, the data source may reject the row without an error you can see.

powerfxRequired field left out
Patch(BugList, Defaults(BugList), {
Severity: { Value: "Critical" }
})  // Title is required — rows not created

How to spot: Wrap the Patch in IfError and display the result. This works with Dataverse; for SharePoint, the error may still be swallowed, but IfError catches what it can.

powerfxCatch the error
IfError(
Patch(BugList, Defaults(BugList), { Severity: { Value: "Critical" } }),
Notify("Failure: " & FirstError.Message, NotificationType.Error)
)

Fix: Always supply every required field, even if you provide a placeholder value. Use a variable default when the form doesn’t collect them.

powerfxProvide required field with default
Patch(BugList, Defaults(BugList), {
Title: txtTitle.Text,
Severity: { Value: "Critical" }
})

Delegation Limits Make Your Target Disappear

Using a Filter as the first argument of Patch is dangerous when the filter cannot be delegated. For example:

powerfxNon-delegable filter may miss the target
Patch(
Filter(BugList, Status.Value = "Open"),  // not delegable
Defaults(BugList),
{ Title: "Mystery Bug" }
)

Power Apps brings only the first 500 (or 2000) records locally. If the intended record is beyond that limit, Filter returns zero rows, and Patch ends up using Defaults—again creating a new row.

How to spot: The operation always creates a new row instead of updating the expected one.

Fix: Patch directly to the table and identify the record with a delegable LookUp or a primary key.

powerfxTarget with LookUp
Patch(
BugList,
LookUp(BugList, BugID = varBugID),  // delegable when BugID is indexed
{ Status: { Value: "Resolved" } }
)
Delegation

Always check the delegation status of every filter and lookup in a Patch call. If the source is wrapped in a non-delegable function, you’re patching against a local subset.

Permission Barriers That Don’t Surface in the App

The least‑obvious cause: the end user does not have permission to create or update records in the data source. The Patch runs in the app, but when the request reaches the data source, it’s denied.

How to spot: The Patch works in the maker’s session (who is an admin) but fails consistently for every other user. The permission change is the variable.

Fix: Verify that the user’s security role on the data source includes at least Create and Write privileges for the table. For SharePoint, that means the Contribute permission level; for Dataverse, assign the appropriate role with Write access to the table and record.

Network & Connector Hiccups with No Error Handling

Sometimes the data source is temporarily unavailable, the connector times out, or the network drops a packet. Without an IfError wrapper, the user never knows.

How to spot: Intermittent failures that you cannot reproduce. The Patch occasionally does nothing.

Fix: Wrap every critical Patch in IfError. Use the success branch to update the UI and the error branch to notify the user.

powerfxResilient patch with user feedback
IfError(
Patch(BugList, varCurrentBug, { Status: { Value: "Resolved" } }),
Notify("Save failed. Please try again.", NotificationType.Error),
Notify("Bug updated.", NotificationType.Success)
)

Build a Smart Save Pattern

The most effective way to avoid all these issues is to centralise your save logic. Encapsulate Patch inside a helper (if you use Component Libraries) or at least apply the same pattern every time:

  • Capture the record in a variable.
  • Convert all data types explicitly.
  • Use the correct shape for lookups and choices.
  • Include all required fields.
  • Wrap in IfError with a meaningful error message.

This pattern alone catches every cause that throws an error, and it forces you to think about the rest before they become issues.

Quick Reference

CauseTelltale SignImmediate Action
Defaults used for updateNew row appearsPass the existing record
Stale SelectedPatch doesn’t affect the same recordCapture to variable first
Type mismatchColumn stays unchangedUse Value(), DateValue(), etc.
Lookup/choice shapeField is blankUse LookUp or {Value: "..."}
Required field missingNothing savedInclude all required columns
Non-delegable filterUnexpected createPatch to source, target with LookUp
PermissionsWorks for maker, not end userCheck security roles
Transient errorIntermittent no‑saveWrap in IfError

References

  • Original article: “Patch() failures: the 8 reasons your record will not save” by PowerStack Editorial.
  • For official details, see the Power Fx documentation on Microsoft Learn: https://learn.microsoft.com/en-us/power-platform/power-fx/reference/function-patch (placeholder — confirm exact URL before linking).
  • Microsoft Learn: IfError function overview (placeholder).