SapotaCorp

Dataverse Managed Solution Changes Not Visible? 3 Layering Fixes

You shipped a managed solution update, the import succeeded, and the change is not visible in the UI. The solution layering model is almost always the reason. Here is the mental model, the diagnostic queries we run, and the three fixes that cover most real-world cases.

Dataverse Managed Solution Changes Not Visible? 3 Layering Fixes

Key takeaways

  • Managed solution changes that do not appear in the target environment trace to 1 of 3 layering issues: an unmanaged customisation overrides the managed layer, the solution import did not actually run, or the change lives in a higher solution layer than expected.
  • Dataverse layering is a stack. Unmanaged customisations sit on top of managed solutions in priority order; if an unmanaged change exists on a column or form, the managed update does not override it. Removing the unmanaged customisation lets the managed version flow through.
  • Solution layers tool surfaces the actual stack. From Make.PowerApps, open the entity, find Solution Layers, see the order. The view shows exactly which solution owns the current state of each customisation; debug starts here, not in trial-and-error solution import.
  • Solution import that does not actually run is the silent failure. The export-import cycle sometimes shows "imported successfully" while the changes were partial. Verify against the solution layers tool, not against the import confirmation. Re-running the import is cheap and often fixes the partial state.

The release pipeline imports the managed solution cleanly. No errors, no warnings. You open the target environment to verify the form change you made - and the form looks exactly like it did before the deploy.

The instinct is to suspect the deploy. Re-run it, re-export, compare zip contents. Everything checks out. The real cause, almost every time, is Dataverse's solution layering model: your managed solution update is being overridden by a higher-priority layer that nobody remembered was there.

The mental model

Dataverse stores each customizable component as a stack of layers. When the runtime renders a form or applies a business rule, it walks the stack top-to-bottom and takes the first layer that defines that property.

The layer order, highest priority first:

  1. Active (unmanaged) customizations - anything edited directly in the target environment without going through a solution
  2. Unmanaged solutions - containers of unmanaged components (rare in Prod, common in Dev)
  3. Managed solution layers, most recently imported first - your client's project solution, then dependencies, then Microsoft's built-in solutions

When you update a managed solution, you add (or modify) a layer near the top of the managed stack - but still below any unmanaged customization that exists for the same component. If someone added an unmanaged change at any point, it wins.

How components get accidental unmanaged layers

Three common causes:

  1. Someone edited directly in UAT or Prod. Configuration changes made through the maker portal or classic customization without a solution context are unmanaged. One afternoon of "quick fix" creates a layer that silently overrides every future managed deploy.
  2. A user with broad privileges imported an unmanaged solution to test something, and did not uninstall it.
  3. A managed solution was imported with OverwriteUnmanagedCustomizations=false in the pipeline. In some import modes this preserves existing unmanaged layers instead of overwriting them - which is sometimes the correct choice but is usually not what you want on a clean deploy.

Diagnosing the layer stack

Dataverse gives you two ways to inspect the active layer for a component.

UI path: Open the component in the maker portal (a table form, for instance). On the left navigation, look for "Solution Layers" or equivalent. It shows every layer that has defined this component, in priority order. The topmost layer is what users see.

API path (faster for scripting): Use the RetrieveEntityRibbon or the newer /api/data/v9.2/msdyn_solutioncomponentsummary virtual entity to list component layers programmatically.

We have a small PowerShell script that lists the top layer for every form in a target environment:

$envUrl = "https://acme-uat.crm4.dynamics.com"
$token = Get-PacToken -Environment $envUrl
$uri = "$envUrl/api/data/v9.2/msdyn_solutioncomponentsummary?" +
       "`$filter=msdyn_componenttype eq 60 and _msdyn_solutioncomponentname_value ne null&" +
       "`$select=msdyn_name,msdyn_solutionname,msdyn_ismanaged"
$response = Invoke-RestMethod -Uri $uri -Headers @{ Authorization = "Bearer $token" }
$response.value | Group-Object -Property msdyn_name | ForEach-Object {
    $top = $_.Group | Where-Object { $_.msdyn_ismanaged -eq $false } | Select-Object -First 1
    if (-not $top) { $top = $_.Group | Select-Object -First 1 }
    [pscustomobject]@{
        Component = $_.Name
        TopLayer  = $top.msdyn_solutionname
        Managed   = $top.msdyn_ismanaged
    }
}

Anything with Managed: False in the TopLayer is an unmanaged override.

Three fixes

Fix 1: remove the unmanaged layer (most common case).

In the maker portal's Solution Layers view, the top unmanaged layer has a "Remove active customization" option. Using it removes the unmanaged customization for that specific component, letting the next layer down (your managed layer) become active.

Caveats:

  • This applies per component. If the unmanaged change spans ten components, you remove 10 times.
  • If the unmanaged layer had a change the business actually wanted, you will remove that change too. Confirm before clicking.

Fix 2: merge the unmanaged change into your solution, then redeploy.

If the unmanaged change is legitimate (a real business fix applied out-of-process), the right fix is to pull it into your Dev environment, add it to the solution properly, and ship it through the pipeline. Then remove the unmanaged layer in UAT/Prod as in Fix 1.

This is the scenario where direct changes happen for good reasons during an incident. The cleanup afterwards is to merge back into source.

Fix 3: import with OverwriteUnmanagedCustomizations=true.

The PowerPlatformImportSolution pipeline task takes this flag. Setting it true tells Dataverse to remove any conflicting unmanaged customizations when the managed import runs.

We use this on Test (where there should never be intentional unmanaged changes) but not on UAT or Prod (where an unplanned overwrite could erase an in-flight hotfix).

The prevention we enforce

After two full-day debug sessions on layering issues, we now enforce four rules on every project:

  • Service principal deploys only to UAT and Prod. Human accounts cannot import unmanaged solutions there.
  • Customization is locked in UAT and Prod via security roles - no user has the privilege to edit forms, fields, or views directly.
  • Any hotfix applied directly must be backfilled into source control within 48 hours, with an automated reminder if it has not been done.
  • A pre-release layering scan runs the PowerShell check above and flags any unexpected unmanaged layers before the pipeline kicks off a deploy.

The layering model is not the bug. The bug is forgetting the layering model exists and making changes outside it. The four rules above keep the model predictable, and when something does slip through, the diagnostic script tells you exactly where to look.


Need senior engineers for Power Platform, Dataverse, or Dynamics 365 work? See Sapota's Power Platform services — Apps, Automate, BI, and D365 F&O / Business Central delivery from $1,800/engineer/month.

Contact Us Now

Share Your Story

We build trust by delivering what we promise – the first time and every time!

We'd love to hear your vision. Our IT experts will reach out to you during business hours to discuss making it happen.

WHY CHOOSE US

"Collaborate, Elevate, Celebrate where Associates - Create Project Excellence"

SapotaCorp beyond the IT industry standard, we are

  • Certificated
  • Assured quality
  • Extra maintenance

Tell us about your project