A guide to different error handling functions and patterns


Power Apps error handling is a critical aspect of any canvas app build. Power Fx or other functionality may not always run as planned, so we should greet users with clear guidance. We may also need to track errors for ongoing monitoring & improvements.
In this article, I’ll go over some simple error handling techniques that you can leverage in your canvas apps.
Intro
Power Apps error handling can take a few different forms, from a simple boolean true/false to fully customised messages and logging. Microsoft articles cover some of the concepts (here and here) and are good starting points to get familiar with the topic.
As some of you may know, formula-level error management was a long-time experimental/preview Power Apps feature. This is no longer the case, as of June 2024 it’s now fully GA (Generally Available).
If you’re a regular user of the Power Apps Code Review Tool (which you should be if you’re building canvas apps), you’ll know that error handling is an included pattern in the feedback:
Form controls
A common first step for new makers building data entry experiences in canvas apps is with the form control. These provide useful in-built error handling that’s easy to configure.
1- Use Form.Valid to show if a form is ready to be submitted. This will return false if errors are active or mandatory fields are still blank. Use this to set the Display Mode property of a Submit button:
// Analyse if form is ready for submission. Disable button until then.
If(
myForm.Valid,
DisplayMode.Edit,
DisplayMode.Disabled
)
Copy
2- Use the OnFailure property of a form control to provide a custom experience when a submission fails.
You’re able to configure multiple steps here, such as using the Notify function, sending an email, patching an Errors list or table and more:
I’ve previously covered form control error handling & functionality in more depth, article here.
IsBlank
The IsBlank function returns a boolean true or false value if a control or value is blank. Simply specify the control or value you want to analyse within the function:
This is great for evaluating controls or outputs before submitting data to a data source.
// Determine if control output is blank
IsBlank(txtInput.Text)
Copy
IfError
The IfError function will return a fallback value if a calculation fails. This may be a useful Power Apps error handling technique for invalid division calculations.
In this example, we have two text input controls set to accept numbers only. There’s a label underneath performing a calculation in its Text property:
Entering numbers that cannot be divided correctly will return an error:
The IfError function therefore provided a graceful fallback to a default value of our choice, should an error occur:
// Default to zero if calculation error occurs
IfError(
txtValue01.Text / txtValue02.Text,
0
)
Copy
You can also use IfError to evaluate other actions too, such as patching to a data source. We can customise the fallback to notify a user or add a record to an errors log:
IfError(
// If an error occurs with this patch
Patch(
Characters,
Defaults(Characters),
{Allegiance: "Dark Side"}
// Notify the user
),
Notify(
"Oops, something went wrong",
NotificationType.Error,
2000
)
)
Copy
IsError
The IsError function will detect for the presence of an error and return a boolean true or false value.
Using the same example as above, we can see the value change depending on whether the sum returns an error:
// Evaluate if calculation is an error
IsError(
txtValue01.Text / txtValue02.Text
)
Copy
We can combine IsError with other functions to evaluate other actions too, such as patching to a data source (though, I prefer the IfError approach for this scenario):
If(
IsError(
// If an error occurs with this patch
Patch(
Characters,
Defaults(Characters),
{Allegiance: "Dark Side"}
)
),
// Notify the user
Notify(
"Oops, something went wrong.",
NotificationType.Error,
2000
)
)
Copy
IsBlankOrError
When it comes to Power Apps error handling, IsBlankOrError is one of my favourites. It streamlines logic of two other functions – IsBlank and IfError – into a single function. The output is a boolean true or false.
In the example below, the control is blank (left) or has an error present in its Default property (right):
Using a valid reference in the Default property, or adding valid text to the input control will return false:
// Determine if control is blank or has an error present
IsBlankOrError(txtInput.Text)
Copy
Another good use for this function is to provide visual clues to users. For example, applying the logic to the BorderColor property of a text input control:
// Visual clue to user for text acceptance
If(
IsBlankOrError(Self.Text),
Color.Red,
Color.Black
)
Copy
App OnError
The OnError property is a great way to capture any unhandled errors that occur anywhere in your app. An unhandled error is any error occurring that isn’t using any of the Power Apps error handling techniques above.
To access this property, in design mode select App, then from the list of properties select OnError:
As this is capturing unhandled errors app-wide, we can utilise Power Fx to find the location of the error. Adding the following code to the OnError property will do just that:
// Find source of unhandled error
Notify(
$"{FirstError.Message}, Observed: {FirstError.Observed}, Source: {FirstError.Kind}",
NotificationType.Error,
2000
)
Copy

There are a couple of extra outputs in FirstError; Kind, HTTPResponse & HTTP StatusCode. I rarely see an output from the HTTP ones, but Kind will return an integer value relating to the error:
// Find source of unhandled error
Notify(
$"{FirstError.Message}, Observed: {FirstError.Observed}, Source: {FirstError.Source}, Kind: {FirstError.Kind}",
NotificationType.Error,
2000
)
Copy
The number relates to one of 27 ErrorKind values, as per this Power Apps error handling reference. It might not be a seamless experience to keep cross-checking ErrorKind values to the table shown, so I prefer to store either as a list, table or Named Formula that I can lookup to.
Here’s the Power Fx logic if you wish to add the Named Formula logic yourself:
// Error Kind logic
nfErrorKinds = Table(
{ErrorKindValue: 0, ErrorKindText: "None"},
{ErrorKindValue: 1, ErrorKindText: "Sync"},
{ErrorKindValue: 2, ErrorKindText: "MissingRequired"},
{ErrorKindValue: 3, ErrorKindText: "CreatePermission"},
{ErrorKindValue: 4, ErrorKindText: "EditPermissions"},
{ErrorKindValue: 5, ErrorKindText: "DeletePermissions"},
{ErrorKindValue: 6, ErrorKindText: "Conflict"},
{ErrorKindValue: 7, ErrorKindText: "NotFound"},
{ErrorKindValue: 8, ErrorKindText: "ConstraintViolated"},
{ErrorKindValue: 9, ErrorKindText: "GeneratedValue"},
{ErrorKindValue: 10, ErrorKindText: "ReadOnlyValue"},
{ErrorKindValue: 11, ErrorKindText: "Validation"},
{ErrorKindValue: 12, ErrorKindText: "Unknown"},
{ErrorKindValue: 13, ErrorKindText: "Div0"},
{ErrorKindValue: 14, ErrorKindText: "BadLanguageCode"},
{ErrorKindValue: 15, ErrorKindText: "BadRegex"},
{ErrorKindValue: 16, ErrorKindText: "InvalidFunctionUsage"},
{ErrorKindValue: 17, ErrorKindText: "FileNotFound"},
{ErrorKindValue: 18, ErrorKindText: "AnalysisError"},
{ErrorKindValue: 19, ErrorKindText: "ReadPermission"},
{ErrorKindValue: 20, ErrorKindText: "NotSupported"},
{ErrorKindValue: 21, ErrorKindText: "InsufficientMemory"},
{ErrorKindValue: 22, ErrorKindText: "QuotaExceeded"},
{ErrorKindValue: 23, ErrorKindText: "Network"},
{ErrorKindValue: 24, ErrorKindText: "Numeric"},
{ErrorKindValue: 25, ErrorKindText: "InvalidArgument"},
{ErrorKindValue: 26, ErrorKindText: "Internal"},
{ErrorKindValue: 27, ErrorKindText: "NotApplicable"}
);
Copy
Error
Perhaps slightly lesser known is the ability to create your own errors. We can do this by using the Error function.
In the example below, I have two Date Picker controls. Before submission, a check must occur to ensure the Start Date isn’t before the End Date. The OnSelect property of a button will perform the validation:
We can add a message & error kind to the Error function like so:
// Validate if start is before end, show error if so
If(
dtpStartDate.SelectedDate > dtpEndDate.SelectedDate,
Error(
{
Message: "Start date must be before end date",
Kind: ErrorKind.Validation
}
)
)
Copy
Common scenarios
You can use Power Apps error handling in all sorts of ways, so get creative and provide high-quality in-app experiences when things may not work as planned. The most common ones I use are below.
Patching to a single data source
As already shown above, it’s good practice to wrap error handling around any patch statements. I like to notify the user that something has gone wrong, but also use the Trace function to capture additional information that can be visible in Monitor. You could also patch a record to an errors table or send an email to admins:
IfError(
// If an error occurs with this patch
Patch(
Characters,
Defaults(Characters),
{Allegiance: "Dark Side"}
// Notify the user & send info to Monitor console
),
Notify(
"Oops, something went wrong",
NotificationType.Error,
2000
);
Trace(
$"Patching error logged at {Now()}",
TraceSeverity.Error,
{
OSType: Host.OSType,
SessionID: Host.SessionID,
Message: "Creation of record in Characters tbl has failed",
User: nfLoggedOnUser.displayName,
Screen: App.ActiveScreen.Name
}
)
)
Copy
Patching to successive data sources
You may want to patch a table, then patch another only if the first patch was successful. If it wasn’t successful, don’t process the 2nd patch.
You can use IfError again to implement this Power Apps error handling technique.
IfError(
// Try Patch 01
Patch(
Characters,
Defaults(Characters),
{
Title: txtNewCharacter01. Text,
Allegiance: "Dark Side"
}
),
// Notify if first Patch fails
Notify(
"First action failed",
NotificationType.Error,
2000
),
// Try Patch 02 if 01 was successful
Patch(
Characters,
Defaults(Characters),
{
Title: txtNewCharacter02. Text,
Allegiance: "Rebels"
}
),
// Notify if second Patch fails
Notify(
"Second action failed",
NotificationType.Error,
2000
)
)
Copy
Suppression
A regular occurrence when working with the Office 365 Users connector is blank user data. This might be a property not populated in the users profile, or they’ve not updated their profile image.
Calls to the connector always need a value passed in and will fail if an expected parameter is blank:
The API will continue to be called in your app unless a value is passed in. Alternatively, you can use error handling to suppress and provide a fallback.
In the example of a user image, that might look like:
// Show sample image if user image can't be resolved
IfError(
Office365Users.UserPhotoV2(cmbUserDirectory.Selected.Mail),
SampleImage
)
Copy
You could opt for using IsBlankOrError for this scenario too:
// Show sample image if user image can't be resolved
If(
IsBlankOrError(Office365Users.UserPhotoV2(cmbUserDirectory.Selected.Mail)),
SampleImage
)
Copy
Logging unhandled errors
In an attempt to continuously improve apps and general UX, it’s important to try & catch any unhandled errors. We can use the app OnError property to capture these by doing something like the following:
1- Get the error details using FirstError.
2- Display the information to the user via the Notify function.
3- Send information about the unhandled error to Monitor, using the Trace function.
4- Patch a dedicated ‘Unhandled errors’ SharePoint list.
All relevant actions run within the Concurrent function and, where required, have their own error handling applied. For logged-on user information & error kinds, I’m using a Named Formula:
With(
{ // Construct string to log error msg, source & kind
tvErrorLog: Concatenate(
FirstError.Message,
", Observed: ",
FirstError.Observed,
", Source: ",
FirstError.Source,
", Kind: ",
// Find ErrorKind text from Named Formula tbl
LookUp(
nfErrorKinds,
ErrorKindValue = FirstError.Kind
).ErrorKindText,
", DetailResponse: ",
FirstError.Details.HttpResponse,
", DetailCode: ",
FirstError.Details.HttpStatusCode
)
},
Concurrent(
// Notification to user
Notify(
tvErrorLog,
NotificationType.Error,
2000
),
// Send details to Monitor via Trace function
Trace(
$"Patching error logged at {Now()}",
TraceSeverity.Error,
{
OSType: Host.OSType,
SessionID: Host.SessionID,
Message: "Unhandled error",
User: nfLoggedOnUser.displayName,
Screen: App.ActiveScreen.Name,
ErrorLog: tvErrorLog
}
),
// Attempt to patch unhandled error details to SharePoint list
If(
IsError(
Patch(
'Unhandled Errors Log',
Defaults('Unhandled Errors Log'),
{
Title: tvErrorLog,
User: nfLoggedOnUser.displayName,
UserEmail: nfLoggedOnUser.mail,
DateTime: Now()
}
)
),
Trace(
$"Patching error log failed",
TraceSeverity.Warning
)
)
)
)
Copy
As a result, we can see details of the unhandled error in Monitor:
Also in the SharePoint list:
About the Author

Craig White, MVP
Microsoft MVP 🏛️ Power Platform Ecosystem Architect ✍️ Blogger @ platformsofpower.net 🔋 #PowerAddicts
Reference:
White, C (2025). Power Apps Error Handling Essentials. Available at: Power Apps Error Handling Essentials – Platforms of Power [Accessed: 15th January 2025].