{"record":{"id":"aedbdf4e2f4329b2","repo":"dotnet/runtime","slug":"assemblynametoload-must-be-marked-with-blazorw-aedbdf","errorCode":null,"errorMessage":"${assemblyNameToLoad} must be marked with 'BlazorWebAssemblyLazyLoad' item group in your project file to allow lazy-loading.","messagePattern":"(.+?) must be marked with 'BlazorWebAssemblyLazyLoad' item group in your project file to allow lazy-loading\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/native/libs/Common/JavaScript/loader/assets.ts","lineNumber":297,"sourceCode":"\n    if (loadedLazyAssemblies.has(assemblyNameWithoutExtension)) {\n        return false;\n    }\n\n    const assemblyNameToLoadDll = assemblyNameWithoutExtension + \".dll\";\n    const assemblyNameToLoadWasm = assemblyNameWithoutExtension + \".wasm\";\n\n    let dllAsset: AssemblyAsset | null = null;\n    for (const asset of lazyAssemblies) {\n        const fileName = lazyAssetFileName(asset.virtualPath);\n        if (fileName === assemblyNameToLoadDll || fileName === assemblyNameToLoadWasm) {\n            dllAsset = asset;\n            break;\n        }\n    }\n\n    if (!dllAsset) {\n        throw new Error(`${assemblyNameToLoad} must be marked with 'BlazorWebAssemblyLazyLoad' item group in your project file to allow lazy-loading.`);\n    }\n\n    await fetchAssembly(dllAsset);\n    loadedLazyAssemblies.add(assemblyNameWithoutExtension);\n\n    if (loaderConfig.debugLevel !== 0) {\n        const pdbNameToLoad = assemblyNameWithoutExtension + \".pdb\";\n        const pdbAssets = loaderConfig.resources?.pdb;\n        let pdbAssetToLoad: AssemblyAsset | undefined;\n        if (pdbAssets) {\n            for (const pdbAsset of pdbAssets) {\n                if (lazyAssetFileName(pdbAsset.virtualPath) === pdbNameToLoad) {\n                    pdbAssetToLoad = pdbAsset;\n                    break;\n                }\n            }\n        }\n        if (!pdbAssetToLoad) {","sourceCodeStart":279,"sourceCodeEnd":315,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/native/libs/Common/JavaScript/loader/assets.ts#L279-L315","documentation":"Thrown by fetchLazyAssembly() when the requested assembly name cannot be matched against any entry in loaderConfig.resources.lazyAssembly. The .NET runtime lazy-load system requires the assembly to be declared at build time so the boot manifest lists it as lazy. Without the manifest entry, the loader has no URL/hash and refuses to load. It is a configuration-vs-request contract violation, not a network problem.","triggerScenarios":"Calling dotnetApi.invokeAssembly or Platform::LoadAssembly for a name (e.g. 'MyPlugin.dll') that was not declared via <BlazorWebAssemblyLazyLoad Include=\"MyPlugin.dll\" />. Also triggered by Router OnNavigateAsync loading a page whose component sits in an undeclared assembly, or by calling fetchLazyAssembly('Foo') directly when resources.lazyAssembly is empty or omits Foo.","commonSituations":"Adding a Razor component library referenced only from a lazy route but forgetting the BlazorWebAssemblyLazyLoad item. Renaming an assembly without updating the lazy-load list. Plugin systems that try to load arbitrary DLLs without declaring them at build time. Upgrading .NET version and missing the new requirement to list satellite/dependency assemblies as lazy too.","solutions":["Add <BlazorWebAssemblyLazyLoad Include=\"AssemblyName.dll\" /> to the .csproj that produces the app (not the library).","Verify the exact name passed to load matches the Include (case-sensitive, with .dll or .wasm extension).","Rebuild and republish so the boot JSON manifest regenerates with the new lazyAssembly entry.","If the assembly is loaded eagerly elsewhere, remove the lazy-load request instead, or split the dependency so only lazy parts are lazy.","For Blazor routing, set Assembly extra in <Router AdditionalAssemblies> AND list it in BlazorWebAssemblyLazyLoad."],"exampleFix":"// before: Router references a lazy page but project lacks the item\n// App.razor\n<Router AppAssembly=\"@typeof(Program).Assembly\"\n        AdditionalAssemblies=\"new[] { typeof(MyPlugin.Pages.Page1).Assembly }\" />\n\n// after: add to Server/Client .csproj\n<ItemGroup>\n  <BlazorWebAssemblyLazyLoad Include=\"MyPlugin.dll\" />\n</ItemGroup>","handlingStrategy":"validation","validationCode":"import { loaderConfig } from './config';\nfunction canLazyLoad(assemblyName: string): boolean {\n  const lazy = loaderConfig.resources?.lazyAssembly ?? [];\n  const target = assemblyName.replace(/\\.(dll|wasm)$/, '');\n  return lazy.some(a => {\n    const file = (a as any).virtualPath.split('/').pop() ?? '';\n    return file.replace(/\\.(dll|wasm)$/, '') === target;\n  });\n}\n// before calling fetchLazyAssembly:\nif (!canLazyLoad('MyPlugin.dll')) {\n  console.error('Add <BlazorWebAssemblyLazyLoad Include=\"MyPlugin.dll\" /> to .csproj');\n}","typeGuard":"function isLazyLoadable(assemblyName: string): assemblyName is string {\n  const lazy = loaderConfig.resources?.lazyAssembly ?? [];\n  return lazy.some(a => (a as any).virtualPath?.endsWith(assemblyName));\n}","tryCatchPattern":"try {\n  await dotnetApi.invokeAssembly('MyPlugin', 'EntryPoint');\n} catch (e) {\n  if (e instanceof Error && e.message.includes('BlazorWebAssemblyLazyLoad')) {\n    // surface build-config instruction to user\n  } else throw e;\n}","preventionTips":["Maintain a single source of truth for lazy assemblies (a constants file) and validate the .csproj against it in CI.","Add a smoke test that attempts to load each declared lazy assembly after publish.","Wire Router.OnNavigateAsync to pre-touch lazy assemblies so the error surfaces during navigation, not at first component render."],"tags":["blazor","configuration","lazy-loading","msbuild"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}