{"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":"exception","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/60108ba66eb7d1d12f595480091b4ad80a24b172/src/native/libs/Common/JavaScript/loader/config.ts#L1-L36","documentation":"validateLoaderConfig() throws when resources is missing, resources.coreAssembly is missing, or coreAssembly array is empty. coreAssembly holds the framework assemblies (System.Private.CoreLib etc.) that must be present before any user code runs. The boot manifest produced by MSBuild populates this; an empty array means the publish output is incomplete.","triggerScenarios":"withConfig called with resources: {} or resources.coreAssembly: []. Manually constructing a LoaderConfig without copying the framework assembly list. A custom boot config that omitted coreAssembly. Build publish output truncated.","commonSituations":"Hand-editing the generated boot JSON. Migrating from older SDK where coreAssembly was not a separate field. Publishing with a trimmed/incomplete _framework directory. Using a config from a different app.","solutions":["Use the dotnet.runtimeconfig.json / dotnet.boot.config.json produced by dotnet publish — do not handcraft resources.","If merging configs, ensure the source contains coreAssembly before mergeLoaderConfig runs.","Re-run dotnet publish to regenerate the manifest.","Verify the SDK version is consistent (coreAssembly was introduced for partitioned framework downloads)."],"exampleFix":"// before\nbuilder.withConfig({ mainAssemblyName: 'App.dll', resources: {} });\n\n// after: load the generated manifest\nconst config = await fetch('./_framework/dotnet.boot.config.json').then(r => r.json());\nbuilder.withConfig(config);","handlingStrategy":"validation","validationCode":"function hasCoreAssemblies(cfg: any): boolean {\n  return Array.isArray(cfg?.resources?.coreAssembly) && cfg.resources.coreAssembly.length > 0;\n}","typeGuard":"function isValidResources(r: unknown): r is { coreAssembly: unknown[] } {\n  return !!r && typeof r === 'object' && Array.isArray((r as any).coreAssembly) && (r as any).coreAssembly.length > 0;\n}","tryCatchPattern":"try { await dotnet.create(); } catch (e) {\n  if (/resources\\.coreAssembly.*required/.test((e as Error).message)) {\n    // reload the boot manifest and retry\n  } else throw e;\n}","preventionTips":["Never construct LoaderConfig by hand — always use the published boot config.","Validate resources.coreAssembly.length > 0 in a smoke test after publish.","Keep SDK versions consistent across build and runtime so the manifest schema matches.","If merging configs, verify the source has coreAssembly before calling mergeLoaderConfig."],"tags":["configuration","loader","publish","msbuild"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}