{"record":{"id":"fcc192a43c887fce","repo":"Unity-Technologies/UnityCsReference","slug":"cannot-add-modulename-after-unitylinker-has-run","errorCode":null,"errorMessage":"Cannot add {moduleName} after UnityLinker has run because it has a non-empty managed assembly. Types found: {string.Join<Type>(\", \", types)}.","messagePattern":"Cannot add (.+?) after UnityLinker has run because it has a non-empty managed assembly\\. Types found: (.+?)\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Editor/Mono/Modules/PostStrippingModuleAdder.cs","lineNumber":36,"sourceCode":"        m_targetData = targetData;\n    }\n\n    public void AddModule(string moduleName)\n    {\n        if (IsModuleIncluded(moduleName))\n            return;\n\n        // Check that the module has no managed component\n        var coreModulePath = InternalEditorUtility.GetEngineCoreModuleAssemblyPath();\n        var moduleAssemblyPath = Path.Combine(Path.GetDirectoryName(coreModulePath), $\"UnityEngine.{moduleName}Module.dll\");\n\n        //a managed assembly is still getting generated for this module, check if the assembly contains no types\n        if (File.Exists(moduleAssemblyPath))\n        {\n            var assembly = CurrentAssemblies.LoadFromPath(moduleAssemblyPath);\n            var types = assembly.GetTypes();\n            if (types.Length > 0)\n                throw new ArgumentException($\"Cannot add {moduleName} after UnityLinker has run because it has a non-empty managed assembly. Types found: {string.Join<Type>(\", \", types)}.\");\n        }\n\n        // Check that all the module's dependencies are already on the list\n        var moduleDependencyNames = ModuleMetadata.GetModuleDependencies(moduleName);\n        var moduleDependencies = new List<LinkerToEditorData.ReportData.Dependency>();\n\n        var missingDependencyNames = new List<string>();\n        foreach (var dependency in moduleDependencyNames)\n        {\n            if (!IsModuleIncluded(dependency))\n            {\n                missingDependencyNames.Add(dependency);\n\n                //no need to process this entry further as it is missing from the included module list\n                continue;\n            }\n\n            moduleDependencies.Add(new LinkerToEditorData.ReportData.Dependency","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/Unity-Technologies/UnityCsReference/blob/225b0fbdb57cc17d094e8056b71f8314aba56f73/Editor/Mono/Modules/PostStrippingModuleAdder.cs#L18-L54","documentation":"Thrown by PostStrippingModuleAdder when attempting to add a module after the Unity managed-code linker (UnityLinker) has already run and the module's UnityEngine.{name}Module.dll still contains types. Adding such a module post-stripping would re-introduce managed code that stripping already removed.","triggerScenarios":"Calling the module-add API (after IL stripping) for a module whose assembly was not fully stripped — types remain, indicating the linker did not process it for removal.","commonSituations":"Custom post-stripping module registration logic runs out of order. Stripping configuration (managedStrippingLevel) changed mid-build. Module added via editor script after a partial build.","solutions":["Ensure the module is added BEFORE stripping runs (correct build phase ordering).","Lower managedStrippingLevel or exclude the assembly from stripping so the post-stripping invariant holds, or ensure the assembly is genuinely empty.","Re-run a full clean build so stripping and module-add operate on a consistent state."],"exampleFix":"// before: add module after linker left types in the assembly\nAddModule(\"MyModule\"); // throws\n// after: move registration to pre-stripping phase\n// or exclude the assembly in link.xml\n<assembly fullname=\"UnityEngine.MyModuleModule\" preserve=\"all\"/>","handlingStrategy":"validation","validationCode":"var path = Path.Combine(Path.GetDirectoryName(InternalEditorUtility.GetEngineCoreModuleAssemblyPath()), $\"UnityEngine.{moduleName}Module.dll\");\nbool canAddPostStrip = !File.Exists(path) || CurrentAssemblies.LoadFromPath(path).GetTypes().Length == 0;","typeGuard":null,"tryCatchPattern":"try { AddModule(name); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"non-empty managed assembly\"))\n{ /* move add to pre-stripping phase */ }","preventionTips":["Register modules before the UnityLinker step.","Keep build phase ordering consistent.","Run clean builds after changing stripping config."],"tags":["unity","stripping","linker","modules","managed-code"],"backgroundTag":null,"analyzedSha":"225b0fbdb57cc17d094e8056b71f8314aba56f73","analyzedAt":"2026-08-13T19:07:19.849Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}