Your app just silently failed. The user clicked Save. Nothing happened. No message. No confirmation. No idea if their record was written — or quietly dropped into the void.
That’s one of the most frustrating experiences in any app. And in Power Apps, it happens more often than it should.
The good news? Power Apps gives you everything you need to catch database errors and surface them to users in a clear, helpful way. You just need to know where to look — and how to wire it up correctly.
The Problem: Silent Failures Are Everywhere
Most Power Apps makers start with a Patch() call and move on. It works in testing, so it ships. But production is different. Connections drop. Permission errors surface. Required fields get missed. Edit conflicts occur.
When errors happen without any handling in place, users are left confused. They re-submit data, create duplicates, or give up entirely. Meanwhile, you — the maker — have no idea anything went wrong.
Therefore, error handling isn’t optional polish. It’s a core part of building a reliable Power Apps database error handling strategy.
Before You Start: Enable Formula-Level Error Management
Power Fx supports formula-level error handling, and it’s turned on by default for all new apps. However, some older apps may have it disabled. Without it, functions like IfError, IsError, and Error won’t work correctly.
To verify it’s enabled:
- Open your canvas app for editing
- Go to Settings > Updates > Retired
- Confirm that Disable formula-level management is turned off
When this setting is enabled, errors are returned as error values — not silently converted to blanks. This distinction matters a lot for reliable error detection.
What Is Power Apps Database Error Handling?
Power Apps error handling refers to the set of functions and techniques that allow you to detect, capture, and respond to errors during database operations — such as writing to Dataverse, SQL Server, or SharePoint.
These errors can come from failed Patch() calls, permission issues, invalid data types, constraint violations, or network timeouts. According to Microsoft Learn, functions that modify data — including Patch, Collect, Remove, Update, and SubmitForm — report errors in two ways: as an error return value from the operation itself, and through the Errors() function after the operation.
The primary functions you’ll use for Power Apps database error handling are IfError(), IsError(), IsBlankOrError(), Errors(), and Error().
Key Functions: What They Do and When to Use Them
IfError() — Your First Line of Defence
IfError() tests values until it finds an error. If it discovers one, it evaluates a replacement value and stops further processing. A default result can also be supplied for when no errors are found. Its structure resembles the If function — IfError tests for errors, while If tests for true.
Syntax:
IfError( Value1, Replacement1 [, Value2, Replacement2, ... [, DefaultResult ] ] )
Example — catching a Patch failure:
IfError(
Patch(Employees, Defaults(Employees), {Name: txtName.Text, Department: txtDept.Text}),
Notify("Failed to save: " & FirstError.Message, NotificationType.Error),
Notify("Record saved successfully!", NotificationType.Success)
)
Within the replacement formula, FirstError gives you a record with four key fields: Kind (error category), Message (user-friendly description), Source (where the error originated), and Observed (where it surfaced). FirstError is always equivalent to First(AllErrors).
Important — stopping chained operations: When you chain formulas with a semicolon, the second one runs even if the first fails. Wrapping both inside IfError() prevents this:
IfError(
Patch(DS1, Defaults(DS1), {Field1: txtValue.Text}),
Notify("Problem saving to DS1: " & FirstError.Message, NotificationType.Error),
Patch(DS2, Defaults(DS2), {Field2: txtOther.Text}),
Notify("Problem saving to DS2: " & FirstError.Message, NotificationType.Error)
)
Errors() — Checking Errors After a Write
The Errors() function queries a data source after an operation and returns a table of errors. It’s particularly useful for forms, because it lets you display error messages inline without needing to capture errors in a state variable.
Syntax:
Errors( DataSource [, Record ] )
The table returned by Errors() contains these columns: Record (the record that had the error), Column (the column that caused it, if applicable), Message (description for the user), and Error (an ErrorKind code for formula use).
Key ErrorKind values include:
| ErrorKind | What It Means |
|---|---|
ErrorKind.Conflict | Another user changed the same record — use Refresh() and retry |
ErrorKind.ConstraintViolation | One or more constraints were violated |
ErrorKind.MissingRequired | A required field value is missing |
ErrorKind.CreatePermission | User lacks permission to create records |
ErrorKind.EditPermission | User lacks permission to edit records |
ErrorKind.Sync | Error reported by the data source — check Message for details |
ErrorKind.Validation | General validation issue |
Example — displaying errors after Patch():
Patch(Orders, Defaults(Orders), {OrderName: txtOrder.Text});
If(
!IsEmpty(Errors(Orders)),
Notify(First(Errors(Orders)).Message, NotificationType.Error),
Notify("Order created successfully!", NotificationType.Success)
)
Note that per Microsoft Learn, Power Apps does not attempt to detect conflicts for Dataverse tables — the Errors() conflict detection is relevant for data sources like SharePoint lists.
IsError() and IsBlankOrError() — Conditional Checks
IsError() returns a Boolean true or false based on whether a value contains an error. It’s useful when you want to branch logic after storing a result in a variable.
Set(varResult, Patch(Projects, Defaults(Projects), {Title: txtTitle.Text}));
If(
IsError(varResult),
UpdateContext({showErrorBanner: true}),
Navigate(SuccessScreen)
)
IsBlankOrError() tests for either a blank value or an error — equivalent to Or(IsBlank(X), IsError(X)). Microsoft recommends using it in older apps being migrated to formula-level error management, where a blank previously represented both null values and errors.
App.OnError — The Global Error Safety Net
App.OnError is a property on the App object that runs every time an unhandled error occurs anywhere in the app. It’s your last line of defence — useful for logging or showing a generic fallback message.
Add this to your App.OnError property to surface detailed diagnostics:
Notify(
Concatenate(
FirstError.Message,
" | Source: ", FirstError.Source,
" | Observed: ", FirstError.Observed
),
NotificationType.Error
)
One critical distinction: App.OnError cannot replace the error like IfError() can. By the time OnError runs, the error has already happened. Use it for logging and fallback messaging — not for recovery logic.
How to Display Errors to Users: Four Practical Approaches
Approach 1: Notify() Banners — Fastest to Implement
Notify() shows a banner at the top of the screen. It supports four types: Success, Error, Warning, and Information. The default timeout is 10 seconds (10,000ms) and the character limit is 500 characters.
Notify("Unable to save your record. Please try again.", NotificationType.Error)
Set the Timeout to 0 to keep the notification on screen until the user dismisses it — useful for critical errors:
Notify("Critical save failure. Contact your administrator.", NotificationType.Error, 0)
Approach 2: Inline Error Label on the Form
For forms, showing the error inline — near the Submit button — gives users immediate context without breaking their flow.
- Add a Label below your Submit button
- Set
Visibleto:!IsBlank(varErrorMessage) - Set
Textto:varErrorMessage - Set
Colorto red:RGBA(196, 49, 75, 1)
IfError(
Patch(Contacts, Defaults(Contacts), {FullName: txtName.Text}),
UpdateContext({varErrorMessage: "Save failed: " & FirstError.Message}),
UpdateContext({varErrorMessage: ""});
Navigate(ConfirmScreen)
)
You can also use Errors() directly in a label’s Text property without any variables:
Label.Text = First(Errors(Contacts, EditRecord)).Message
Approach 3: Form Control’s OnFailure Property
If you’re using the built-in Form control with SubmitForm(), use the Form’s OnFailure property directly — no IfError needed:
// Submit button OnSelect
SubmitForm(frm_SubmitData)
// Form's OnSuccess property
Navigate('Success Screen')
// Form's OnFailure property
Notify("Error: the record could not be saved. " & FirstError.Message, NotificationType.Error)
This is the cleanest approach for Form-based UIs and keeps error handling neatly separated from submission logic.
Approach 4: Error Popup / Overlay — Best for Critical Failures
For serious errors that could cause data loss, a modal popup is more attention-grabbing than a banner.
- Create a Container on your screen with a card-style rectangle, error icon, message label, and a dismiss button
- Set the container’s
VisibletovarShowErrorPopup
IfError(
Patch(Invoices, Defaults(Invoices), {Amount: txtAmount.Text}),
UpdateContext({
varShowErrorPopup: true,
varErrorMessage: "Error: " & FirstError.Message
}),
Navigate(SuccessScreen)
)
The dismiss button sets varShowErrorPopup back to false. For conflict errors, you can also show a Reload button whose OnSelect calls Revert(DataSource, EditRecord) to reset the record.
Real-World Use Cases
Leave Request Submission: A user submits a leave request, but the Dataverse connection drops mid-write. With IfError(), you catch the failure and display: “Your leave request could not be saved. Please check your connection and try again.” The form stays populated so the user doesn’t lose their input.
HR Onboarding Form: A required field like Employee ID is missing. Errors() returns ErrorKind.MissingRequired along with a message from Dataverse. You surface this inline next to the relevant field so HR staff knows exactly what to fix.
Inventory Conflict Resolution: Two warehouse workers update the same stock record simultaneously. Errors() returns ErrorKind.Conflict with the message “Another user has modified the record you’re trying to modify.” You show a Reload button using Visible = !IsEmpty(LookUp(Errors(Inventory, EditRecord), Error = ErrorKind.Conflict)) to guide the user to retry.
How It Compares: Modern vs. Legacy Error Handling
Before formula-level error management, Power Apps returned errors as blank values — making it impossible to distinguish between “no record found” and “something broke.” That’s why IsBlankOrError() exists: to help older apps migrate safely.
| Approach | Best Use Case |
|---|---|
IfError() + FirstError | Wrapping any Patch or expression — primary method |
Errors() + IsEmpty() | Post-write checks; inline form labels; conflict detection |
IsError() | Branching logic after storing a result in a variable |
IsBlankOrError() | Legacy apps migrating to formula-level error management |
Form OnFailure | Form control submissions using SubmitForm() |
App.OnError | Global fallback logging and messaging for unhandled errors |
For new apps, always prefer IfError() with FirstError.Message for inline operations, and App.OnError as a safety net. For more on building reliable apps, see our post on Building Approval Workflows in Power Apps with Power Automate.
Conclusion
Silently failing apps erode user trust fast. With IfError(), Errors(), IsError(), and App.OnError, Power Apps gives you a complete toolkit to catch database errors the moment they happen — and communicate them clearly using banners, inline labels, form properties, or custom popups. Start with IfError() on every Patch() call, add App.OnError as your global net, and use the Form’s OnFailure for submit-based flows. Your users will know exactly what happened — and what to do next.
References
- Error, IfError, IsError, and IsBlankOrError functions — Microsoft Learn
- Errors function — Microsoft Learn
- Error handling in Power Apps (Coding Guidelines) — Microsoft Learn
- Power Fx error handling — Microsoft Learn
- Notify function — Microsoft Learn
- App object and OnError property — Microsoft Learn
Discover more from Power Solution
Subscribe to get the latest posts sent to your email.
