Building Resilient Patch Operations in Power Apps
Catch and respond to save failures with Errors(), Validate(), and Notify() for a better app experience.
In many canvas apps, the Patch function is the primary way to create or update records. Without explicit error handling, a failed save can leave the app in an inconsistent state—or, worse, let a user navigate away as if the operation succeeded. By wrapping Patch with the Errors(), Validate(), and Notify() functions, you can build a more resilient flow that validates input before submission and communicates exact failure details to the user.
Scenario Overview
To illustrate, we'll build a simple customer feedback app. The user enters a name, a numeric rating (1–5), and optional comments. On submission, the app saves the record to a SharePoint list named FeedbackRecords. The app will:
- Validate the rating is within the allowed range before enabling the Submit button.
- Patch the record when Submit is clicked.
- Show a success notification and navigate to a confirmation screen if the save is successful.
- Display a detailed error message and remain on the form if the save fails.
Setting Up the SharePoint List
Create a new SharePoint list called FeedbackRecords with the following columns:
| Column Name | Type | Notes |
|---|---|---|
| Title (rename to CustomerName) | Single line of text | Identifies the customer |
| Rating | Number | Min = 1, Max = 5 |
| FeedbackDate | Date | Default = today's date |
| Comments | Multiple lines of text | Optional |
After creation, set the Rating column's minimum to 1 and maximum to 5 in the column settings. This enforces the range at the data-source level.
Building the App Screens
Create a blank canvas app and add two screens:
- FeedbackFormScreen – contains the input controls.
- ThankYouScreen – displays after a successful save.
On FeedbackFormScreen, add:
- Text input for CustomerName (named
txt_CustomerName) - Text input for Rating (named
txt_Rating) - Text input for Comments (named
txt_Comments) - Button labeled Submit (named
btn_Submit)
On ThankYouScreen, add a label thanking the user and a button to go back (optional).
The Basic Patch without Error Handling
Initially, the Submit button's OnSelect property might contain only the Patch and a Navigate:
Patch(
FeedbackRecords,
Defaults(FeedbackRecords),
{
CustomerName: txt_CustomerName.Text,
Rating: Value(txt_Rating.Text),
FeedbackDate: Today(),
Comments: txt_Comments.Text
}
);
Navigate(ThankYouScreen);If the Patch fails (for example, because the rating is out of range or the data source is unreachable), the app still navigates to the confirmation screen. The user believes the save was successful when it was not.
Adding Error Handling with Errors()
The Errors() function returns a table of errors for a given data source from the last operation. When Patch uses the same data source, Errors() reflects the outcome of that operation.
Update the button's OnSelect property:
Patch(
FeedbackRecords,
Defaults(FeedbackRecords),
{
CustomerName: txt_CustomerName.Text,
Rating: Value(txt_Rating.Text),
FeedbackDate: Today(),
Comments: txt_Comments.Text
}
);
If(
Not(IsEmpty(Errors(FeedbackRecords))),
// There was an error
Notify(
"The feedback record could not be saved.",
NotificationType.Error
),
// Success
Navigate(ThankYouScreen)
);Now, when the Patch fails, a red banner appears at the top of the screen, and the user stays on the form. If it succeeds, they move to the confirmation screen.
A note on Errors() behavior: Every time you call Patch on a data source, the error state for that source is reset. Errors() only returns the errors from the most recent operation. This means you don't have to worry about stale errors, but you must check the result immediately after the Patch.
Making the Error Message More Descriptive
The Errors() function returns a table with columns: Column, Message, Error, and Record. By using Concat(), you can combine multiple error messages into one string.
Replace the Notify call inside the button's OnSelect:
If(
Not(IsEmpty(Errors(FeedbackRecords))),
Notify(
Concat(
Errors(FeedbackRecords),
Column & ": " & Message,
Char(10)
),
NotificationType.Error
),
Navigate(ThankYouScreen)
);The Char(10) inserts a line break between multiple errors, making them easier to read in the notification banner.
Pre-Validating the Rating with Validate()
Before the user even tries to submit, you can use the Validate() function to check whether the current input is acceptable according to the data source's rules. Validate does not attempt to save; it only returns error information if the record would be invalid.
Disable the Submit button when the data is invalid by using the DisplayMode property of btn_Submit:
If(
IsBlank(
Validate(
FeedbackRecords,
Defaults(FeedbackRecords),
{
CustomerName: txt_CustomerName.Text,
Rating: Value(txt_Rating.Text),
FeedbackDate: Today(),
Comments: txt_Comments.Text
}
)
),
DisplayMode.Edit,
DisplayMode.Disabled
);When the entire record passes validation, Validate returns blank, and the button is enabled. Otherwise, Validate returns a table of errors, and the button becomes disabled.
Highlighting the Invalid Field
A more user-friendly approach is to highlight the specific field that fails validation. For the Rating text input, set its BorderColor property to:
If(
IsBlank(
Validate(
FeedbackRecords,
"Rating",
Value(txt_Rating.Text)
)
),
Color.Black,
Color.Red
);Here, we use the single-column variation of Validate, specifying the column name "Rating". If the value is valid (blank result), the border stays black; if invalid, it turns red.
This pattern can be repeated for any column you want to highlight. The Validate function checks not only the range constraints but also other column rules like required fields.
Validation Timing and the Experimental Error Handling Setting
When you use Value(txt_Rating.Text) inside Validate, a non-numeric entry will cause an error that might not be caught by Validate alone. If you prefer to avoid this, you can wrap the value with a check like If(IsMatch(txt_Rating.Text, "\\d+"), Value(txt_Rating.Text), Blank()).
Alternatively, use IfError() to handle conversion errors. Formula-level error management is generally available in current Power Apps environments (it was experimental before 2023, but is now on by default). Wrap the conversion: IfError(Value(txt_Rating.Text), Blank()) returns blank instead of throwing if the text is not numeric.
Security and Delegation Considerations
- Errors() and Validate() work with data sources that support them, such as SharePoint, SQL Server, and Dataverse. For custom connectors, you may need to implement your own error detection.
- Delegation is not a concern with these functions, as they operate directly on the client side with the data source's metadata.
- The Validate function automatically uses the column's metadata from the data source (min/max, required, etc.), so any changes to the data source rules will immediately affect your app's validation logic.
Common Mistakes and Troubleshooting
| Mistake | Symptom | Solution |
|---|---|---|
| Checking Errors() before Patch executes | Errors() always shows previous error state | Ensure the Patch call comes before the If(Not(IsEmpty…)) check, or call Errors() immediately after Patch. |
| Not resetting the error state manually (if needed) | After a successful Patch, Errors() still returns old errors | The Errors function resets on each data operation; if you need a clean state, you can perform a dummy operation or simply restructure your logic. |
| Using IfError without formula-level error management enabled | App shows unexpected errors on type conversion | Formula-level error management is GA (on by default) in current environments. If you are using an older app, go to Settings → General to enable it. For most apps, avoid conversion errors by using IsMatch or IfError to guard non-numeric inputs before passing to Validate. |
| Using Validate with an unsupported data source | Validate always returns blank | Check the official documentation for your data source. For custom sources, implement manual validation with If statements. |
Final Recommendation
Combine Errors(), Validate(), and Notify() to create a robust pattern for handling Patch failures in Power Apps. Always validate before patching when possible, but never rely solely on client-side validation—always check the actual outcome of the operation. This approach reduces user frustration and helps administrators and developers diagnose issues quickly.
References
- Matthew Devaney, Power Apps Patch Function Error Handling – https://www.matthewdevaney.com/power-apps-patch-function-error-handling/ – Original reference that inspired this article.
- Microsoft Learn, Errors function in Power Apps – https://learn.microsoft.com/en-us/power-platform/power-fx/reference/function-errors
- Microsoft Learn, Validate function in Power Apps – https://learn.microsoft.com/en-us/power-platform/power-fx/reference/function-validate
- Microsoft Learn, Notify function in Power Apps – https://learn.microsoft.com/en-us/power-platform/power-fx/reference/function-showerror
Learn how small coding practices—like using descriptive names, flattening conditions, and simplifying logic—can make your apps easier to update and less error-prone.
Move past the gallery and discover the hidden patterns for validation, navigation, and smart submission handling in your data entry forms.
PowerShell unlocks admin capabilities that the Power Platform admin center simply doesn’t offer—from recovering deleted apps to blocking trial licenses. Here’s how to wield them safely.