Skip to content

Troubleshooting Guide: Top 30 Errors During Dynamics 365 On-Prem → Online Migrations (OP2OL)

Migrating from Microsoft Dynamics 365 On-Premise to Online (OP2OL) involves complex data transformation. This guide serves as a technical reference for the 30 most common migration failures, including specific error codes (0x8004...), SQL transaction logs, and API throttling limits.

Raajshekhar Rajan Raajshekhar Rajan · · 18 min read
Troubleshooting Guide: Top 30 Errors During Dynamics 365 On-Prem → Online Migrations (OP2OL)
TALK TO AN ENGINEER

Planning a migration?

Get a free 30-min call with our engineers. We'll review your setup and map out a custom migration plan — no obligation.

Schedule a free call
  • 1,500+ migrations completed
  • Zero downtime guaranteed
  • Transparent, fixed pricing
  • Project success responsibility
  • Post-migration support included

Section 1: Critical Telemetry & Benchmarks

Use these verified ranges to configure your ETL tools (ADF, KingswaySoft, SSIS).

Metric Safe Threshold Failure Threshold Context
SQL Timeout < 120 Seconds > 120 Seconds Hard limit for TDS/SQL connections. Source: TDS Limits
Batch Size (Complex) 250 - 500 records > 1,000 records For Quotes, Orders, Cases (Entities with heavy plugin logic).
Batch Size (Simple) 1,000 - 2,000 records > 5,000 records For Tasks, Contacts, Leads.
Concurrency 2 - 4 Threads > 52 Threads Per User Limit. Source: Service Protection API
Attachment Size < 25 MB > 35 MB Hard Exchange Online limit. Source: Exchange Online Limits

Section 2: The Master Error Database (01–30)

Error Severity & Frequency Reference

The table below labels each error by how often it blocks migrations (Common / Occasional / Rare) and how severely it does so (Critical = migration cannot proceed; High = significant data loss or rework risk; Medium = isolated failures, recoverable).

# Error Severity Frequency
01 System.TimeoutException Critical Common
02 Generic Plugin Error (0x80040216) Critical Common
03 Circular Reference / Referential Integrity Critical Common
04 Transaction Log Full Critical Common
05 ISV Code Aborted (Legacy Assembly) High Common
06 429 Too Many Requests Critical Common
07 Principal with Id Does Not Exist Critical Common
08 Invalid Argument (Picklist / OptionSet) High Common
09 Attachment Size Exceeds Limit High Common
10 Duplicate Key Violation High Common
11 Privilege Denied (SecLib::AccessCheckEx) Critical Common
12 Max Depth Exceeded (Infinite Loop) Critical Occasional
13 Date Out of Range High Occasional
14 Entity Reference Cannot Be Found High Common
15 Currency Mismatch Critical Occasional
16 String or Binary Data Truncated Medium Common
17 Entity State is Invalid High Occasional
18 Root Element is Missing (XML) Medium Occasional
19 Managed Property Error High Occasional
20 Missing Dependency High Occasional
21 Attachment Limit Exceeded (Exchange Sync) High Occasional
22 Workforce / Resource Constraint High Rare
23 Duplicate Lookup Reference High Common
24 Team Template Mismatch Medium Rare
25 Invalid Plugin Assembly (Sandbox) High Occasional
26 Business Process Flow Error Medium Occasional
27 PrincipalAccess Missing (POA Table) Critical Common
28 SQL Connection Closed Medium Occasional
29 Web Resource Content Invalid Medium Rare
30 Portal/Site Setting Missing High Rare

Migration Load-Order Dependency Map

The sequence below is the authoritative load order for a standard CE/Dataverse migration. Violating this sequence is the leading cause of errors 03, 07, 15, 22, and 27.

Step Entity / Group Depends On Notes
1 transactioncurrency Base and non-base currencies. Must exist before any Money field.
2 uom / uomschedule Unit groups and units. Required by Products.
3 calendar / calendarrule Required by systemuser (work hours) and bookableresource.
4 systemuser calendar Map On-Prem GUIDs to Entra IDs before this step.
5 team systemuser Owner teams must exist before records that reference them.
6 account (Pass 1 — stub) systemuser, transactioncurrency Create with parentaccountid = NULL.
7 contact (Pass 1 — stub) systemuser, account (stub) Create with parentcustomerid = NULL.
8 account (Pass 2 — patch lookups) contact (stub) Set primarycontactid.
9 contact (Pass 2 — patch lookups) account (Pass 2) Set parentcustomerid.
10 Core transactional entities account, contact, systemuser Cases, Opportunities, Orders, etc.
11 annotation / activitymimeattachment Core entities Notes and email attachments.
12 bookableresource systemuser, calendar Field Service only.
13 PrincipalObjectAccess (POA) All entities above Must be last. Use GrantAccessRequest, not direct insert.

Tooling Matrix

The table below maps each common error category to which migration tools handle it natively versus which require custom code.

Error / Scenario KingswaySoft Azure Data Factory SSIS (vanilla) Config Migration Tool (CMT) SDK / Custom Code
429 / Retry-After handling Native Native (retry policy) Manual N/A Manual
Multi-Pass ingestion (circular refs) Native (pass config) Manual (pipeline stages) Manual N/A Manual
User GUID remapping Native (lookup map) Manual Manual N/A Manual
BypassCustomPluginExecution Native (header option) Manual (header inject) Manual N/A Manual
UpsertRequest (duplicate keys) Native Native Manual N/A Manual
OptionSet / Picklist validation Native (value map) Manual Manual N/A Manual
POA table (GrantAccessRequest) Not supported Not supported Not supported Not supported Required
Portal / Site Settings (Error 30) Not supported Not supported Not supported Native Not supported
BPF Stage GUID remapping Manual Manual Manual N/A Manual
Attachment chunking (>25 MB) Native Manual Manual N/A Manual

01. System.TimeoutException (SQL Execution Limit)

  • Category: Infrastructure / SQL
  • Severity: Critical | Frequency: Common
  • Root Cause: The query execution exceeded the hard 2-minute (120s) limit on the Dataverse SQL layer. This frequently occurs when reading "heavy" entities like Annotation (Notes) or ActivityPointer where table sizes exceed 1GB.
  • Official Citation: Dataverse SQL Query Limitations (2-minute limit)
  • Technical Resolution: Do not use standard OData (/api/data/v9.2/) for bulk extraction of >500k rows. Use the TDS Endpoint (SQL) with strict pagination.
  • Reproducible Artifact (T-SQL):
-- BAD: SELECT * FROM [Annotation] (Will Timeout)
-- GOOD: Deterministic Pagination using OFFSET/FETCH
SELECT [AnnotationId], [Subject], [NoteText], [CreatedOn]
FROM [Annotation]
WHERE [CreatedOn] >= '2023-01-01'
ORDER BY [CreatedOn] ASC
OFFSET 0 ROWS FETCH NEXT 5000 ROWS ONLY;
  • Verification: Run the query in SSMS connected to the TDS endpoint. If execution time > 55s, reduce batch size to 2,000.

02. Generic Plugin Error (0x80040216)

  • Category: Server-Side Logic
  • Severity: Critical | Frequency: Common
  • Root Cause: A synchronous plugin registered on Pre-Operation or Post-Operation is failing. This blocks the transaction.
  • Official Citation: Bypass Custom Business Logic
  • Technical Resolution: Do not disable plugins manually. Use the BypassCustomPluginExecution parameter in your API calls. This requires the migration user to have the prvBypassCustomPluginExecution privilege.
  • Reproducible Artifact (HTTP Header):
POST [Organization URI]/api/data/v9.2/accounts HTTP/1.1
MSCRM.BypassCustomPluginExecution: true
Content-Type: application/json
 
{
  "name": "Migrated Account",
  "creditlimit": 10000
}
  • Verification: Check the Plugin Trace Log table in Dataverse. If the bypass is working, no logs will be generated for the migration user during the load.

03. Record Is Unavailable (Referential Integrity / Circular Reference)

  • Category: Data Mapping
  • Severity: Critical | Frequency: Common
  • Root Cause: Record A references Record B, but Record B has not been created yet. Common in "Parent Account" scenarios where Account X is the parent of Account Y, but Account Y is processed first.
  • Technical Resolution: Implement Multi-Pass Ingestion.
    1. Pass 1 (Create): Insert all records with Lookup fields set to NULL.
    2. Pass 2 (Update): Iterate through the source data again and update only the Lookup fields.
  • Reproducible Artifact (C# Logic):
// Pass 1: Create Stub
Entity account = new Entity("account");
account["name"] = "Child Branch";
account["parentaccountid"] = null; // Intentional Null
Guid createdId = service.Create(account);
 
// Pass 2: Patch Relationship (After all accounts exist)
Entity patch = new Entity("account");
patch.Id = createdId;
patch["parentaccountid"] = new EntityReference("account", parentGuid);
service.Update(patch);
  • Telemetry Threshold: If "Missing Reference" errors exceed 5% of a batch, pause and verify your load order (e.g., Users > Accounts > Contacts).

04. Generic SQL Error (Transaction Log Full)

  • Category: Database Constraints
  • Severity: Critical | Frequency: Common
  • Root Cause: Massive bulk inserts are filling the SQL transaction log buffer on the target instance before a commit can occur.
  • Official Citation: Azure SQL Resource Limits (DTU-based)
  • Technical Resolution: Dataverse does not allow you to change the Recovery Model to "Simple." You must control this via client-side batching. Reduce your ExecuteMultipleRequest batch size.
  • Benchmark:
    • Safe: 10 requests per batch.
    • Risky: > 1000 requests per batch (High risk of log overflow).
  • Verification: Monitor the Dataverse Analytics dashboard > "SQL Failures."

05. ISV Code Aborted (Legacy Assembly)

  • Category: Legacy Extensibility
  • Severity: High | Frequency: Common
  • Root Cause: Custom Workflow Activities or Plugins are using unsupported .NET Framework versions (e.g., 4.5.2) or deprecated Xrm.Page references.
  • Official Citation: Supported Extensions & .NET Framework
  • Technical Resolution: Recompile all custom assemblies to .NET 4.6.2 (or 4.7.1) before migration.
  • Verification: Run the Power Apps Solution Checker on your solution zip file. It will flag Type or namespace not found errors for deprecated code.

06. Service Protection Limit (429 Too Many Requests)

  • Category: API Throttling
  • Severity: Critical | Frequency: Common
  • Root Cause: The migration user has exceeded 6,000 requests within a 5-minute sliding window.
  • Official Citation: Service Protection API Limits
  • Technical Resolution: Do not use a fixed Thread.Sleep(). You must parse the Retry-After header returned by the 429 response.
  • Reproducible Artifact (C# / .NET SDK):
try {
    service.Execute(request);
}
catch (FaultException<OrganizationServiceFault> ex) {
    if (ex.Detail.ErrorCode == -2147015902) { // 429 Code
        // Extract the 'Retry-After' duration mandated by the server
        int retrySeconds = 5; // Default fallback
        if (ex.Detail.ErrorDetails.Contains("Retry-After")) {
            retrySeconds = Convert.ToInt32(ex.Detail.ErrorDetails["Retry-After"]);
        }
        Thread.Sleep(retrySeconds * 1000);
        // Retry logic here...
    }
}

07. Principal with Id Does Not Exist

  • Category: Security / User Mapping
  • Severity: Critical | Frequency: Common
  • Root Cause: The OwnerId (User or Team GUID) in the source data does not exist in the target Entra ID (Azure AD).
  • Technical Resolution: Create a User Mapping Table. Do not attempt to migrate users with their old On-Prem GUIDs unless you have pre-seeded the target with those exact GUIDs (which is rare).
  • Artifact (Mapping Strategy): | Source GUID | Target GUID | Source Name | Target Name | | :--- | :--- | :--- | :--- | | 1111-aaa... | 2222-bbb... | John Doe | John Doe | | 3333-ccc... | 9999-zzz... | (Terminated User) | "Stub User" / Admin |
  • Verification: Perform a WhoAmI request or simple Retrieve on the target systemuser table using the Target GUID before starting the batch.

08. Invalid Argument (Picklist / OptionSet)

  • Category: Data Schema
  • Severity: High | Frequency: Common
  • Root Cause: The source data contains an integer value (e.g., 999) that is not defined in the target OptionSet metadata.
  • Technical Resolution:
    • Option A: Map invalid values to a "Default" (e.g., 999 -> 1).
    • Option B (Admin): Programmatically create the missing option using InsertOptionValueRequest.
  • Reproducible Artifact (SDK Request):
var request = new InsertOptionValueRequest {
    AttributeLogicalName = "industrycode",
    EntityLogicalName = "account",
    Value = 999, // The missing value
    Label = new Label("Legacy Industry", 1033)
};
service.Execute(request);

09. Attachment Size Exceeds Limit

  • Category: File Storage
  • Severity: High | Frequency: Common
  • Root Cause: Files in Annotation or ActivityMimeAttachment exceed the default 5MB limit.
  • Official Citation: Exchange Online Message Limits
  • Technical Resolution:
    1. Update System Settings > Email > Max file size to 131,072 KB (128 MB).
    2. For files > 128 MB, migrate to Azure Blob Storage and leave a URL link.
  • Verification: Attempt to upload a 10MB file via the Unified Interface. If it fails, the setting has not propagated.

10. Duplicate Key Violation

  • Category: SQL Constraints
  • Severity: High | Frequency: Common
  • Root Cause: Attempting to insert a record with a Primary Key (GUID) that already exists in the target.
  • Technical Resolution: Switch from CreateRequest to UpsertRequest. This operation checks for existence: if the record exists, it updates it; if not, it creates it.
  • Reproducible Artifact (C#):
var account = new Entity("account", new Guid("source-guid-here"));
account["name"] = "Updated Name";
 
var request = new UpsertRequest { Target = account };
var response = (UpsertResponse)service.Execute(request);
 
// response.RecordCreated tells you if it was an Insert or Update

11. Privilege Denied (SecLib::AccessCheckEx Failed)

  • Category: Security Roles
  • Severity: Critical | Frequency: Common
  • Root Cause: The Application User or Service Principal performing the migration lacks the specific privilege (e.g., prvCreateAccount or prvAppendTo) for the entity being migrated.
  • Official Citation: Dataverse Security Roles & Privileges
  • Technical Resolution: Do not rely on a custom "Migration Role." Assign the standard System Administrator role to the Application User. If using a Service Principal, ensure the Application User is enabled and the Client Secret has not expired.
  • Verification: Navigate to Power Platform Admin Center > Environments > Users. Select the Application User and click "Manage Roles" to confirm "System Administrator" is checked.

12. Max Depth Exceeded (Infinite Loop)

  • Category: Workflow / Business Logic
  • Severity: Critical | Frequency: Occasional
  • Root Cause: A synchronous workflow or plugin is triggering itself recursively. Dataverse enforces a hard "Max Depth" limit (default is 8) to prevent infinite loops.
  • Official Citation: Message Processor & Max Depth
  • Technical Resolution: You must deactivate all workflows and Power Automate flows triggered by "Record Creation" or "Record Update" on the target entities before migration starts.
  • Reproducible Artifact (PowerShell):
# Use the Microsoft.Xrm.Data.PowerShell module to disable workflows
$workflows = Get-CrmRecords -EntityLogicalName workflow -FilterAttribute statecode -FilterOperator eq -FilterValue 1 # 1 = Active
foreach ($wf in $workflows) {
    Disable-CrmRecord -EntityLogicalName workflow -Id $wf.workflowid
    Write-Host "Disabled Workflow: $($wf.name)"
}
  • Verification: Attempt to manually create a record in the UI. If it triggers a 5-second loading spinner followed by an error, a process is still active.

13. Date Out of Range

  • Category: Data Format
  • Severity: High | Frequency: Occasional
  • Root Cause: Source data contains dates older than 1/1/1753 (SQL MinDate) or 1/1/1900 (Dataverse MinDate). This is common in legacy "Date of Birth" fields or placeholder dates.
  • Official Citation: DateTimeAttributeMetadata Class
  • Technical Resolution: Implement a transformation rule in your ETL: IF SourceDate < '1900-01-01' THEN SET TargetDate = NULL
  • Reproducible Artifact (C# Transformation):
DateTime? safeDate = sourceDate;
if (sourceDate.HasValue && sourceDate.Value.Year < 1900)
{
    safeDate = null; // Or use new DateTime(1900, 1, 1);
}
entity["birthdate"] = safeDate;

14. Entity Reference Cannot Be Found

  • Category: Polymorphic Lookups
  • Severity: High | Frequency: Common
  • Root Cause: A lookup field (e.g., parentcustomerid) points to a GUID that does not exist in either the Account or Contact table. This often happens when the referenced record was deleted in the source but the relationship was not cascaded.
  • Technical Resolution: Do not fail the entire batch. Catch the FaultException, log the specific GUID as a "Broken Link," and retry the create operation without that specific lookup value.
  • Verification: Query the Failures table in your migration tool. If you see >10% failure rate, run a SQL query on the source to identify "Orphaned Records" before migrating.

15. Currency Mismatch (TransactionCurrencyId)

  • Category: Finance / Multi-Currency
  • Severity: Critical | Frequency: Occasional
  • Root Cause: You are migrating a record with a Money field (e.g., revenue), but the transactioncurrencyid lookup is null, or the referenced currency does not exist in the target.
  • Official Citation: Transaction Currency (Currencies) Entity
  • Technical Resolution:
    1. Migrate the transactioncurrency table first.
    2. Ensure the isocurrencycode (e.g., USD, EUR) matches exactly.
    3. If the source transactioncurrencyid is null, default it to the target organization's Base Currency.

16. String or Binary Data Would Be Truncated

  • Category: Data Schema
  • Severity: Medium | Frequency: Common
  • Root Cause: The text in the source column is longer than the MaxLength defined in the target Dataverse column (e.g., Source: 200 chars, Target: 100 chars).
  • Technical Resolution:
    • Fix A (Preferred): Go to the Power Apps Maker Portal, select the Column, and increase "Maximum Character Count."
    • Fix B (Data Loss): Truncate the string in your ETL script.
  • Reproducible Artifact (SQL Truncation):
-- Safer to truncate than to fail
SELECT LEFT([Description], 2000) as [Description], [Subject]
FROM [Incident]

17. Entity State is Invalid

  • Category: Status / Lifecycle
  • Severity: High | Frequency: Occasional
  • Root Cause: Attempting to create a record directly in a "Resolved" or "Inactive" state (e.g., statecode=1). Some system entities do not allow creation in a closed state.
  • Official Citation: Update Entity State (SetStateRequest)
  • Technical Resolution: Two-Step Ingestion:
    1. Create the record in Active state (statecode=0).
    2. Send a separate UpdateRequest or SetStateRequest to close it.
  • Verification: Compare the count of Active vs Inactive records in Source vs Target.

18. Root Element is Missing (XML)

  • Category: Data Structure / Notes
  • Severity: Medium | Frequency: Occasional
  • Root Cause: You are migrating a Note (Annotation) that contains an attached file, but the documentbody (Base64 string) is corrupt, empty, or the mimetype is missing.
  • Technical Resolution: Validate that documentbody is not null and is a valid Base64 string. IF documentbody IS NOT NULL AND mimetype IS NULL SET mimetype = 'application/octet-stream'

19. Managed Property Error

  • Category: Solution Layering
  • Severity: High | Frequency: Occasional
  • Root Cause: You are trying to update a component (like a View, Form, or Attribute) that is part of a Managed Solution where IsCustomizable is set to False.
  • Official Citation: Managed Properties
  • Technical Resolution: You cannot directly modify these components via migration API. You must install a new version of the Managed Solution that contains the desired changes (e.g., longer field length).

20. Missing Dependency

  • Category: Solution Import
  • Severity: High | Frequency: Occasional
  • Root Cause: You are importing a Solution file (.zip) that references a component (e.g., a Global OptionSet or a 3rd Party DLL) that does not exist in the target environment.
  • Technical Resolution:
    1. Unzip the solution and open solution.xml.
    2. Search for the <MissingDependency> tag to identify the missing GUID/Name.
    3. Install the prerequisite solution first.
  • Verification: The import log will explicitly list the "Required Solution Name."

21. Attachment Limit Exceeded (Exchange Sync)

  • Category: Email Integration
  • Severity: High | Frequency: Occasional
  • Root Cause: A migrated email contains an attachment larger than 35 MB. While Dataverse allows files up to 128 MB, Exchange Online has a hard transmission limit of 35 MB (after Base64 encoding overhead).
  • Official Citation: Exchange Online Limits (Message Limits)
  • Technical Resolution: You cannot sync these emails to Outlook. Strategy: Detect attachments > 25 MB during migration. Strip the attachment, upload it to Azure Blob Storage, and append the Blob URL to the email body text.
  • Verification: Check the "Server-Side Synchronization" dashboard for "Permanent Failures" with error code ExchangeAttachmentLimit.

22. Workforce / Resource Constraint

  • Category: Field Service
  • Severity: High | Frequency: Rare
  • Root Cause: Creating a BookableResource record fails because the associated User or Contact does not have a valid Calendar (Work Hours) defined in the target.
  • Official Citation: Set up bookable resources
  • Technical Resolution: Order of Operations:
    1. Migrate calendar and calendarrule entities.
    2. Migrate systemuser.
    3. Migrate bookableresource. Note: If the Calendar is missing, the scheduling engine cannot instantiate the resource.

23. Duplicate Lookup Reference

  • Category: Data Quality
  • Severity: High | Frequency: Common
  • Root Cause: Ambiguous resolution. You are mapping a lookup based on "Name" (e.g., parentcustomerid = "John Smith"), but two records named "John Smith" exist in the target.
  • Technical Resolution: Strict GUID Mapping: Never use text-based lookup resolution for migration. Always map Source GUID to Target GUID.
  • Reproducible Artifact (FetchXML Check):
<fetch aggregate="true">
  <entity name="contact">
    <attribute name="fullname" alias="name_count" aggregate="count"/>
    <attribute name="fullname" alias="name_group" groupby="true"/>
    <order alias="name_count" descending="true"/>
  </entity>
</fetch>

24. Team Template Mismatch

  • Category: Access Teams
  • Severity: Medium | Frequency: Rare
  • Root Cause: You are migrating records that use Access Teams (auto-created teams), but the teamtemplateid refers to a template that does not exist in the target environment.
  • Technical Resolution: Access Team Templates are not solution-aware. You must manually recreate them in the Target environment and map the Old Template ID to the New Template ID in your migration script.

25. Invalid Plugin Assembly (Security)

  • Category: Security / Sandbox
  • Severity: High | Frequency: Occasional
  • Root Cause: The assembly contains code forbidden in the Dynamics 365 Sandbox isolation mode (Partial Trust). Common blockers: System.IO (File access), System.Reflection, or direct SQL connections.
  • Official Citation: Plug-in isolation, trusts, and statistics
  • Technical Resolution: Refactor the code. Move heavy logic or prohibited namespaces to Azure Functions, which can be triggered by a Webhook or Service Bus.

26. Business Process Flow (BPF) Error

  • Category: Process Automation
  • Severity: Medium | Frequency: Occasional
  • Root Cause: The traversedpath field contains a comma-separated list of Stage GUIDs. If the BPF definition in the target has different Stage GUIDs than the source, the record will fail to load.
  • Official Citation: Business process flow entity serialization
  • Technical Resolution: Do not migrate the traversedpath string directly. You must create a "Stage Map" (Source Stage GUID -> Target Stage GUID) and reconstruct the path string during transformation.

27. PrincipalAccess Missing (POA Table)

  • Category: Sharing (Critical)
  • Severity: Critical | Frequency: Common
  • Root Cause: The PrincipalObjectAccess (POA) table governs "Share" and "Assign" rights. Migration fails if the PrincipalId (User) or ObjectId (Record) does not exist yet.
  • Official Citation: Use Record Sharing to Manage Access
  • Technical Resolution: The "Caboose" Strategy: Migration of the POA table must be the absolute last step of the entire project.
    • Step 1: Migrate Users & Teams.
    • Step 2: Migrate All Data.
    • Step 3: Migrate POA Table.
  • Reproducible Artifact (SDK Request):
// Use GrantAccessRequest, not Create. 
// Direct SQL insert into POA is NOT supported in Online.
var grantRequest = new GrantAccessRequest {
    PrincipalAccess = new PrincipalAccess {
        Principal = new EntityReference("systemuser", userId),
        AccessMask = AccessRights.ReadAccess | AccessRights.WriteAccess
    },
    Target = new EntityReference("account", accountId)
};
service.Execute(grantRequest);

28. SQL Connection Closed

  • Category: Connectivity
  • Severity: Medium | Frequency: Occasional
  • Root Cause: Transient network failure between your On-Premise server and the Azure Data Center, causing the SqlConnection to drop.
  • Technical Resolution: Configure the connection string to handle transient failure. Use ConnectRetryCount and ConnectRetryInterval to auto-reconnect on transient drops. For transient SQL errors that survive reconnection (e.g., deadlocks, resource governor rejections), wrap your batch execution in an exponential back-off retry loop — the same pattern used for 429 errors applies here.
  • Artifact (Connection String): Server=tcp:org.crm.dynamics.com,1433;Database=org;Authentication=ActiveDirectoryPassword;ConnectRetryCount=3;ConnectRetryInterval=10;

29. Web Resource Content Invalid

  • Category: UI / JavaScript
  • Severity: Medium | Frequency: Rare
  • Root Cause: JavaScript files contain unsupported DOM manipulation methods like document.getElementById or $("#id"), which fail in the Unified Interface.
  • Technical Resolution: Run the Solution Checker. Replace all jQuery/DOM calls with the Client API (formContext.getControl()).

30. Portal/Site Setting Missing

  • Category: Power Pages (Portals)
  • Severity: High | Frequency: Rare
  • Root Cause: Portal configuration (Adxstudio) relies on specific GUIDs for "Site Settings" and "Snippets." Standard data loaders often generate new GUIDs, breaking the portal linkage.
  • Technical Resolution: Use the Configuration Migration Tool (CMT) provided in the SDK. It supports "Schema validation" and maintains referential integrity specifically for Portal entities.

Scope & Known Limitations

This guide covers Dynamics 365 CE / Dataverse (v9.x) On-Premises to Online migrations using the Dataverse API (v9.2). It does not cover:

  • Finance & Operations (F&O) / ERP migrations — F&O uses a separate data management framework (DIXF) with different error patterns.
  • Dual-write scenarios — Errors arising from dual-write synchronization between CE and F&O are out of scope.
  • Custom virtual entities — Virtual entity data providers introduce third-party API dependencies not addressed here.
  • v8.x source environments — Some errors and API behaviors differ when migrating from Dynamics CRM 2016 (v8.x). Where v8.x-specific behavior is known to differ from v9.x, test against your actual source version before applying the resolutions above.
  • Trial and Sandbox environment API limits — Microsoft applies lower service protection limits on Trial and non-Production Sandbox environments. The thresholds in Section 1 reflect Production environment limits. Validate actual limits for your environment type in the Power Platform Admin Center before configuring concurrency and batch sizes.

Frequently Asked Questions

Can I migrate On-Premise SQL directly to Dataverse?
No. You cannot restore a .bak file to Dataverse. You must use a migration tool (ADF, Scribe, or Custom Scripts) to map the schema and transfer data via API.
How do I handle "CreatedOn" date changes?
By default, creating a record resets CreatedOn to "today." To preserve history, you must map the source CreatedOn field to the overriddencreatedon field in the target.
Why is my migration failing on "OwnerId"?
You cannot migrate a record if the owner (user) is disabled or missing in Office 365. You must map inactive users to a generic "Stub User" or "System Admin" to preserve the record.

More from our Blog