{"record":{"id":"3851a6c3e1769fd5","repo":"egametang/ET","slug":"hot-update-assembly-hotupdatedll-is-duplicated","errorCode":null,"errorMessage":"hot update assembly:{hotUpdateDll} is duplicated","messagePattern":"hot update assembly:(.+?) is duplicated","errorType":"validation","errorClass":"BuildFailedException","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.hybridclr/Scripts/Editor/Share/BuildProcessors/FilterHotFixAssemblies.cs","lineNumber":40,"sourceCode":"        {\n            if (!SettingsUtil.Enable)\n            {\n                Debug.Log($\"[FilterHotFixAssemblies] disabled\");\n                return assemblies;\n            }\n            List<string> allHotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;\n\n            // 检查是否重复填写\n            var hotUpdateDllSet = new HashSet<string>();\n            foreach(var hotUpdateDll in allHotUpdateDllNames)\n            {\n                if (string.IsNullOrWhiteSpace(hotUpdateDll))\n                {\n                    throw new BuildFailedException($\"hot update assembly name cann't be empty\");\n                }\n                if (!hotUpdateDllSet.Add(hotUpdateDll))\n                {\n                    throw new BuildFailedException($\"hot update assembly:{hotUpdateDll} is duplicated\");\n                }\n            }\n\n            var assResolver = MetaUtil.CreateHotUpdateAssemblyResolver(EditorUserBuildSettings.activeBuildTarget, allHotUpdateDllNames);\n            // 检查是否填写了正确的dll名称\n            foreach (var hotUpdateDllName in allHotUpdateDllNames)\n            {\n                if (assemblies.Select(Path.GetFileNameWithoutExtension).All(ass => ass != hotUpdateDllName) \n                    && string.IsNullOrEmpty(assResolver.ResolveAssembly(hotUpdateDllName, false)))\n                {\n                    throw new BuildFailedException($\"hot update assembly:{hotUpdateDllName} doesn't exist\");\n                }\n            }\n\n            // 将热更dll从打包列表中移除\n            return assemblies.Where(ass =>\n            {\n                string assName = Path.GetFileNameWithoutExtension(ass);","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.hybridclr/Scripts/Editor/Share/BuildProcessors/FilterHotFixAssemblies.cs#L22-L58","documentation":"Thrown by FilterHotFixAssemblies.OnFilterBuildAssemblies when a hot-update assembly name appears more than once in the combined list. The code uses a HashSet<string> to detect duplicates; HashSet.Add returns false if the element already exists. A duplicate is a configuration error because it would cause ambiguous assembly filtering and potential double-processing.","triggerScenarios":"OnFilterBuildAssemblies builds hotUpdateDllSet from HotUpdateAssemblyNamesExcludePreserved. If the same assembly name is listed in both hotUpdateAssemblies and hotUpdateAssemblyDefinitions, or duplicated within either list, the HashSet.Add returns false and the exception fires.","commonSituations":"Listing the same assembly in both the 'hotUpdateAssemblies' (string list) and 'hotUpdateAssemblyDefinitions' (definition list) fields of HybridCLRSettings; duplicating an entry within one list (common with Unity inspector array manipulation); refactoring settings where an assembly was moved between lists but not removed from the old one.","solutions":["Open HybridCLRSettings and check for the duplicated assembly name across both hotUpdateAssemblies and hotUpdateAssemblyDefinitions fields.","Remove the duplicate so each hot-update assembly appears exactly once.","If using AssemblyDefinitionAsset references, cross-reference them against the string list to avoid overlaps.","Audit the settings asset file directly in a text editor to catch duplicates the inspector might obscure."],"exampleFix":"// before — settings:\n//   hotUpdateAssemblies: [\"GameLogic\", \"HotUpdate\"]\n//   hotUpdateAssemblyDefinitions: [GameLogic.asmdef]  // \"GameLogic\" duplicated\n// FilterHotFixAssemblies throws: \"hot update assembly:GameLogic is duplicated\"\n\n// fix — keep GameLogic in only one list:\n//   hotUpdateAssemblies: [\"HotUpdate\"]\n//   hotUpdateAssemblyDefinitions: [GameLogic.asmdef]\n\n// programmatic dedup guard before build:\nvar combined = new HashSet<string>(StringComparer.Ordinal);\nforeach (var name in allNames.Where(n => !string.IsNullOrWhiteSpace(n)))\n    if (!combined.Add(name))\n        Debug.LogWarning($\"Duplicate hot-update assembly will be removed: {name}\");","handlingStrategy":"validation","validationCode":"var names = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;\nvar seen = new HashSet<string>(StringComparer.Ordinal);\nforeach (var name in names.Where(n => !string.IsNullOrWhiteSpace(n)))\n{\n    if (!seen.Add(name))\n    {\n        Debug.LogError($\"Duplicate hot-update assembly name detected: '{name}'. \" +\n            \"Check both hotUpdateAssemblies and hotUpdateAssemblyDefinitions for overlap.\");\n    }\n}","typeGuard":"static bool HasNoDuplicates(string[] names)\n{\n    var clean = names.Where(n => !string.IsNullOrWhiteSpace(n));\n    return clean.Count() == new HashSet<string>(clean, StringComparer.Ordinal).Count;\n}","tryCatchPattern":"try\n{\n    BuildPipeline.BuildPlayer(scenes, outputPath, buildTarget, buildOptions);\n}\ncatch (BuildFailedException ex) when (ex.Message.Contains(\"is duplicated\"))\n{\n    Debug.LogError(\"A hot-update assembly name is listed more than once. \" +\n        \"Check hotUpdateAssemblies and hotUpdateAssemblyDefinitions for duplicates.\");\n}","preventionTips":["Cross-check hotUpdateAssemblies (string list) against hotUpdateAssemblyDefinitions (asset list) to avoid overlap.","When moving an assembly between lists, remove it from the old one.","Run a dedup check on the combined assembly name list before building.","Inspect the HybridCLRSettings asset directly to catch duplicates the inspector may not surface."],"tags":["hybridclr","build-processor","hot-update","configuration","duplicate","settings"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}