Canvas Apps offline mode does not push data to the data source
Troubleshooting guidance for Canvas Apps that save data while offline but do not synchronize records to the data source after the device reconnects to the network.
#Issue
A Canvas App is configured for mobile offline mode. The user can enter data while the device is offline, and the device later shows a network connection, but the records are not pushed to the data source.
The device showing Wi-Fi or cellular connectivity does not always mean that Power Apps can reach the required environment, connector, or data source. Synchronization can also be delayed or blocked by an offline profile, a failed submit formula, permissions, validation errors, or a record conflict.
#Applies to
- Microsoft Power Apps Canvas Apps
- Power Apps Mobile
- Dataverse offline profiles and offline-enabled tables
- Canvas Apps using
Patch,Collect,SubmitForm, or local collections - Apps that use
SaveDataandLoadDatafor local storage
#Important distinction: Dataverse offline sync versus local storage
First identify how the app stores offline data:
- Dataverse offline-first functionality uses an offline profile and synchronizes supported Dataverse tables when the app reconnects.
SaveDataandLoadDatastore data locally in the app. They do not automatically push records to a data source. The app must explicitly read the local records and callPatch,Collect, orSubmitFormwhen connectivity is available.
If the app uses SaveData, simply restoring the network connection will not upload the saved records by itself.
#Common causes
- The table is not included in the app's Dataverse offline profile.
- The required columns or relationships are not configured for offline use.
- The app is using
SaveDatawithout a reconnect-and-upload routine. - The app checks
Connection.Connectedonly once and never retries synchronization. - A
Patch,Collect, orSubmitFormoperation fails because of permissions, required fields, validation, or a connector error. - A local record has no stable client-side ID, so the app cannot identify the record during retry.
- The app tries to synchronize before the device has a usable connection to the environment.
- A record conflict or duplicate causes the server operation to fail.
- The user is signed into a different environment or account than expected.
- The app is still running an older published version.
#Resolution
#1. Confirm the app and data-source design
Document the following before troubleshooting:
- The environment URL and environment name.
- The data source and table used by the app.
- Whether the app uses Dataverse offline profiles or
SaveData/LoadData. - The formula that creates or updates the record.
- The local collection or table that contains records waiting to synchronize.
Do not assume that an offline-enabled Dataverse app and a SaveData app synchronize in the same way.
#2. Verify the Dataverse offline profile
If the app uses Dataverse offline-first functionality:
- Open the app in Power Apps Studio.
- Open the app's offline configuration or offline profile.
- Confirm that the target table is included.
- Confirm that the user has permission to create or update rows in the table.
- Confirm that required related tables and columns are also available offline.
- Save and publish the app after changing the profile.
- Allow the mobile app time to download the updated profile before testing.
If the table is not part of the offline profile, the app may appear to work locally but will not synchronize that table as expected.
#3. Test the connection from inside the app
Show the connection state in a temporary label or status banner:
If(
Connection.Connected,
"Connected",
"Offline"
)
Connection.Connected only reports the device connection state. It does not prove that the app can write successfully to the data source. Use it as an indication to start a retry, and use error handling to confirm the write result.
#4. Add explicit error handling to writes
Wrap write operations in IfError and show the error to the user. For example:
IfError(
Patch(
Orders,
Defaults(Orders),
{
LocalRequestId: varLocalRequestId,
Description: txtDescription.Text,
SyncStatus: "Submitted"
}
),
Notify(
"The record could not be synchronized. It remains on this device and will be retried.",
NotificationType.Error
),
Notify(
"The record was synchronized successfully.",
NotificationType.Success
)
)
Do not clear the local record until the write succeeds. If the formula removes the local record first, a failed upload can result in data loss.
#5. Implement a retry process for SaveData and LoadData
For apps using local storage, keep a local queue with a stable ID and synchronization status. A basic pattern is:
// Add a new local record
Collect(
colPendingUploads,
{
LocalRequestId: GUID(),
Description: txtDescription.Text,
SyncStatus: "Pending",
RetryCount: 0
}
);
SaveData(colPendingUploads, "PendingUploads")
When the app starts or the user selects Sync, attempt to upload only pending records:
If(
Connection.Connected,
ForAll(
Filter(colPendingUploads, SyncStatus = "Pending"),
IfError(
Patch(
Orders,
Defaults(Orders),
{
LocalRequestId: ThisRecord.LocalRequestId,
Description: ThisRecord.Description
}
);
RemoveIf(
colPendingUploads,
LocalRequestId = ThisRecord.LocalRequestId
),
Notify(
"One or more records could not be synchronized.",
NotificationType.Warning
)
)
);
SaveData(colPendingUploads, "PendingUploads"),
Notify(
"The device is still offline. The records remain queued.",
NotificationType.Information
)
)
Treat this as a pattern to adapt to the app's data source and error-handling requirements. For large queues, avoid an unbounded ForAll operation and provide a visible progress or result summary.
#6. Add a visible synchronization status
Show users whether records are pending, synchronized, or failed. A useful status banner can include:
- The number of pending records.
- The last successful synchronization time.
- The last synchronization error.
- A Sync now button.
- A message telling the user not to uninstall the app or clear app data while records remain pending.
Example pending count:
CountRows(Filter(colPendingUploads, SyncStatus = "Pending"))
#7. Check permissions and required fields
After reconnecting, test the same user account while online. Confirm that the user can create or update the target record directly in the data source. Check:
- Create and write permissions on the table.
- Required columns.
- Choice, lookup, and date values.
- Business rules and plug-ins.
- Row-level security.
- Connection references and environment variables.
A device connection cannot bypass a data-source permission or validation failure.
#8. Publish and refresh the mobile app
After changing formulas, tables, or offline configuration:
- Save the app.
- Publish the latest version.
- Close the app completely on the device.
- Reopen Power Apps Mobile.
- Confirm that the correct environment and app version are being used.
- Allow time for the offline profile and app metadata to refresh.
#Beginner-friendly test procedure
- Connect the device to the network and open the published app.
- Confirm that the app shows the expected environment and user.
- Create one test record while online and confirm that it reaches the data source.
- Turn off Wi-Fi and cellular data, then create a second test record.
- Confirm that the offline record appears in the app's pending list.
- Restore the network connection.
- Select Sync now, or wait for the app's documented automatic sync behavior.
- Confirm that the pending count decreases only after a successful response.
- Open the data source and verify the record using its
LocalRequestIdor another unique identifier. - Repeat the test after closing and reopening the app to confirm that pending records survive a restart.
- Test a failed case, such as a missing required value, and confirm that the record remains queued with a useful error message.
#Validation checklist
| Check | Expected result |
|---|---|
| Online create | Record is created in the data source |
| Offline create | Record is retained locally and marked pending |
| Network restored | App detects or allows a synchronization attempt |
| Successful upload | Record appears in the data source and leaves the queue |
| Failed upload | Record remains queued and the user sees an error |
| App restart | Pending records are still available |
| Duplicate prevention | Retrying does not create unintended duplicate records |
| Permissions | The intended user can create or update the target table |
| Published version | The mobile device is running the latest published app |