microsoft / microsoft/WindowsAppSDK

LoadComponent fails for XAML pages in subfolders — embedded XBF indexed by filename only, URI includes subdirectory path

Open
#6,299 3 comments 0 reactions 1 assignee View on GitHub

@guimafelipe is already working on this.

Since Mar 19, 2026.

area-MSIXBuildTools needs-triage
Dominant language
C++
Stars
4.7k
Forks
471
Avg merge
3d 13h
Merged PRs (30d)
28

Description

Describe the bug

Apps with XAML pages organized in subdirectories (e.g. Presentation\Shell.xaml) crash at startup with:

Cannot locate resource from 'ms-appx:///Presentation/Shell.xaml'

or in Uno Platform apps:

Layout cycle detected. Layout is not able to complete.

This is a silent build-time/runtime mismatch — the app builds without errors or warnings but crashes at runtime.

Root cause

The _CalculateXbfSupport target in Microsoft.Build.Msix.Pri.targets (shipped inside the Microsoft.WindowsAppSDK NuGet package since version 1.0.0) sets _SupportXbfAsEmbedFileResources=true by default:

<Target Name="_CalculateXbfSupport">
  <PropertyGroup>
    <_SupportXbfAsEmbedFileResources Condition="'$(_SupportEmbedFileResources)' == 'true' and '$(DisableEmbeddedXbf)' == 'false'">true</_SupportXbfAsEmbedFileResources>
    <_SupportXbfAsEmbedFileResources Condition="'$(DisableEmbeddedXbf)' == 'true'">false</_SupportXbfAsEmbedFileResources>
    <_SupportXbfAsEmbedFileResources Condition="'$(_SupportXbfAsEmbedFileResources)' == '' AND '$(_SupportEmbedFileResources)' == 'true'">true</_SupportXbfAsEmbedFileResources>
  </PropertyGroup>
</Target>

This causes XBF files to be routed to EmbedOutputGroupForPackaging in the GetPriOutputs target:

<_PriOutputsUnexpanded Include="@(_CustomOutputGroupForPackagingOutput)"
    Condition="'%(Extension)' == '.xbf' AND '$(_SupportXbfAsEmbedFileResources)' == 'true'">
  <OutputGroup>EmbedOutputGroupForPackaging</OutputGroup>
</_PriOutputsUnexpanded>

Files in EmbedOutputGroupForPackaging are embedded as binary blobs in resources.pri and indexed only by their filename — the subdirectory prefix is stripped. So Presentation\Shell.xbf becomes Files/Shell.xbf in resources.pri.

Meanwhile, the XAML compiler (Microsoft.WinUI.NET.Markup.Compiler.targets) generates LoadComponent URIs from the Page item's %(Link) metadata — or the project-relative path if Link is not set. Without explicit Link, it emits ms-appx:///Presentation/Shell.xaml, which does not match the flat Files/Shell.xbf in resources.pri.

XAML compiler DLL versions
WinAppSDK Compiler DLL version Package
1.7 3.0.0.2509 Microsoft.WindowsAppSDK
1.8 3.0.0.2602 Microsoft.WindowsAppSDK.WinUI (new sub-package)

The PRI targets (_CalculateXbfSupport, GetPriOutputs) are identical across versions 1.0 through 1.8.

Steps to reproduce

  1. Create an unpackaged WinUI 3 app (WindowsPackageType=None)
  2. Add a Page XAML file in a subfolder (e.g. Presentation\MainPage.xaml)
  3. Build and run → crashes with Cannot locate resource from 'ms-appx:///Presentation/MainPage.xaml'

Reproduces with both pure WinUI 3 projects and Uno Platform single-project apps targeting net10.0-windows10.0.26100.

Note: The Uno SDK's Uno.DefaultItems.targets includes XAML pages via <Page Include="**\*.xaml" .../> without setting Link metadata — this is the source of the mismatch for projects that organize XAML files in subdirectories.

Expected behavior

XAML pages placed in subdirectories load correctly. The LoadComponent URI must match the PRI resource index path.

Actual behavior

App crashes at startup — LoadComponent cannot find the resource because the PRI entry is indexed by flat filename (Files/Shell.xbf) while the XAML compiler generates a URI with the subdirectory path (ms-appx:///Presentation/Shell.xaml).

Workaround

Set <Link>%(Filename)%(Extension)</Link> on all Page items to force the XAML compiler to emit flat ms-appx:/// URIs that match the embedded XBF index:

<!-- Directory.Build.targets -->
<ItemGroup Condition="$(IsWinAppSdk) == 'true'
                      AND ('$(OutputType)'=='Exe' OR '$(OutputType)'=='WinExe')">
  <!--
    XBF files are embedded in resources.pri and indexed by filename only (no path).
    Without Link, XamlCompiler generates ms-appx:///Subfolder/Page.xaml URIs
    that don't match the flat Files/Page.xbf entries.
    IMPORTANT: XAML files must have unique names across all subfolders.
  -->
  <Page Update="**\*.xaml">
    <Link>%(Filename)%(Extension)</Link>
  </Page>
  <Page Update="App.xaml">
    <Link>App.xaml</Link>
  </Page>
</ItemGroup>

Limitation: XamlCompiler.exe always names output XBF by the source %(Filename) (ignoring Link path prefix). XAML files in the same executable project must have unique filenames across all subdirectories — two files with the same name in different folders (e.g. Views\Page.xaml and Controls\Page.xaml) cause an MSB3030 copy error.

Suggested fix

The embedded XBF indexer should preserve the relative path in the PRI index (e.g. Files/Presentation/Shell.xbf instead of Files/Shell.xbf), OR the XAML compiler should automatically set Link to match the flat index when _SupportXbfAsEmbedFileResources=true.

NuGet package versions

Package Version
Microsoft.WindowsAppSDK 1.8.260209005
Microsoft.Windows.SDK.BuildTools 10.0.28000.1-RTM

Packaging type

Unpackaged (WindowsPackageType=None)

Windows version

Windows 11 24H2 (Build 26100)

Additional context

  • Related issue: #5832 ("Upgrading to v1.8 breaks ResourceLoader in unpackaged apps") — same PRI area, different symptom
  • The embed.resfiles intermediate file lists XBF entries by flat filename, confirming paths are stripped
  • This affects any framework built on top of WinUI 3 that uses subdirectory XAML organization (Uno Platform, etc.)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.