{"record":{"id":"c10dc4845bebb10f","repo":"dotnet/runtime","slug":"loader-configuration-error-resources-coreassembl","errorCode":null,"errorMessage":"Loader configuration error: 'resources.coreAssembly' is required and must contain at least one assembly.","messagePattern":"Loader configuration error: 'resources\\.coreAssembly' is required and must contain at least one assembly\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/native/libs/Common/JavaScript/loader/config.ts","lineNumber":18,"sourceCode":"// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under the MIT license.\n\nimport type { Assets, LoaderConfig, LoaderConfigInternal } from \"./types\";\nimport { browserVirtualAppBase } from \"./per-module\";\n\nexport const loaderConfig: LoaderConfigInternal = {};\n\nexport function getLoaderConfig(): LoaderConfig {\n    return loaderConfig;\n}\n\nexport function validateLoaderConfig(): void {\n    if (!loaderConfig.mainAssemblyName) {\n        throw new Error(\"Loader configuration error: 'mainAssemblyName' is required.\");\n    }\n    if (!loaderConfig.resources || !loaderConfig.resources.coreAssembly || loaderConfig.resources.coreAssembly.length === 0) {\n        throw new Error(\"Loader configuration error: 'resources.coreAssembly' is required and must contain at least one assembly.\");\n    }\n}\n\nexport function mergeLoaderConfig(source: Partial<LoaderConfigInternal>): void {\n    defaultConfig(loaderConfig);\n    normalizeConfig(source);\n    mergeConfigs(loaderConfig, source);\n}\n\nfunction mergeConfigs(target: LoaderConfigInternal, source: Partial<LoaderConfigInternal>): LoaderConfigInternal {\n    // no need to merge the same object\n    if (target === source || source === undefined || source === null) return target;\n\n    // Merge collections: target values first, then source values appended/spread on top.\n    mergeResources(target.resources!, source.resources!);\n    // For scalar fields with defaults, prefer source when defined, otherwise keep target default.\n    // We patch source so that Object.assign below copies the correct resolved value.\n    source.appendElementOnExit = source.appendElementOnExit !== undefined ? source.appendElementOnExit : target.appendElementOnExit;","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/dotnet/runtime/blob/290d5ab72cc1102813fbc0406fb186ceadabc340/src/native/libs/Common/JavaScript/loader/config.ts#L1-L36","documentation":"The second guard in validateLoaderConfig(): loaderConfig.resources must exist, must have a coreAssembly array, and that array must contain at least one entry. coreAssembly holds the assemblies required to bring up CoreCLR itself. Without them the runtime cannot initialize, so the loader fails fast.","triggerScenarios":"Calling create()/download()/runMain() when resources is undefined, when resources.coreAssembly is undefined/null, or when resources.coreAssembly is an empty array. Typically a malformed or missing boot config.","commonSituations":"A custom publish profile that strips core assemblies; loading a partial config via withConfig() that omits resources.coreAssembly; the .bin or .json boot config file failed to download/parse so resources came through as empty; hand-rolling LoaderConfig in tests.","solutions":["Regenerate the boot config by republishing the project (dotnet publish) so resources.coreAssembly is populated.","If constructing config manually, ensure resources.coreAssembly is a non-empty array of assembly assets.","Verify the boot config JSON actually loaded — check network tab for the config file and that mergeLoaderConfig received parsed JSON, not undefined.","Confirm no later withConfig() call overwrote resources with an object lacking coreAssembly."],"exampleFix":"// before\nbuilder.withConfig({ mainAssemblyName: 'App', resources: { coreAssembly: [] } });\n\n// after\nbuilder.withConfig({\n  mainAssemblyName: 'App',\n  resources: { coreAssembly: [{ name: 'System.Runtime.dll', hash: '...' }] }\n});","handlingStrategy":"validation","validationCode":"function validateResources(cfg: any) {\n  const core = cfg?.resources?.coreAssembly;\n  if (!Array.isArray(core) || core.length === 0) {\n    throw new Error('Boot config missing resources.coreAssembly — republish.');\n  }\n}\nvalidateResources(getLoaderConfig());","typeGuard":"function hasCoreAssemblies(r: any): r is { coreAssembly: unknown[] } {\n  return Array.isArray(r?.coreAssembly) && r.coreAssembly.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Always source LoaderConfig from the publish output rather than hand-writing it.","Add a CI step that JSON-schema-validates blazor.boot.json.","Log loaderConfig.resources immediately after merge to catch empty merges."],"tags":["config","validation","startup","loader","assemblies"],"analyzedSha":"290d5ab72cc1102813fbc0406fb186ceadabc340","analyzedAt":"2026-08-06T19:57:01.276Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}