egametang/ET · error · BuildFailedException

hot update assembly:{hotUpdateDll} is duplicated

Error message

hot update assembly:{hotUpdateDll} is duplicated

What it means

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.

Source

Thrown at Packages/cn.etetet.hybridclr/Scripts/Editor/Share/BuildProcessors/FilterHotFixAssemblies.cs:40

        {
            if (!SettingsUtil.Enable)
            {
                Debug.Log($"[FilterHotFixAssemblies] disabled");
                return assemblies;
            }
            List<string> allHotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;

            // 检查是否重复填写
            var hotUpdateDllSet = new HashSet<string>();
            foreach(var hotUpdateDll in allHotUpdateDllNames)
            {
                if (string.IsNullOrWhiteSpace(hotUpdateDll))
                {
                    throw new BuildFailedException($"hot update assembly name cann't be empty");
                }
                if (!hotUpdateDllSet.Add(hotUpdateDll))
                {
                    throw new BuildFailedException($"hot update assembly:{hotUpdateDll} is duplicated");
                }
            }

            var assResolver = MetaUtil.CreateHotUpdateAssemblyResolver(EditorUserBuildSettings.activeBuildTarget, allHotUpdateDllNames);
            // 检查是否填写了正确的dll名称
            foreach (var hotUpdateDllName in allHotUpdateDllNames)
            {
                if (assemblies.Select(Path.GetFileNameWithoutExtension).All(ass => ass != hotUpdateDllName) 
                    && string.IsNullOrEmpty(assResolver.ResolveAssembly(hotUpdateDllName, false)))
                {
                    throw new BuildFailedException($"hot update assembly:{hotUpdateDllName} doesn't exist");
                }
            }

            // 将热更dll从打包列表中移除
            return assemblies.Where(ass =>
            {
                string assName = Path.GetFileNameWithoutExtension(ass);

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Open HybridCLRSettings and check for the duplicated assembly name across both hotUpdateAssemblies and hotUpdateAssemblyDefinitions fields.
  2. Remove the duplicate so each hot-update assembly appears exactly once.
  3. If using AssemblyDefinitionAsset references, cross-reference them against the string list to avoid overlaps.
  4. Audit the settings asset file directly in a text editor to catch duplicates the inspector might obscure.

Example fix

// before — settings:
//   hotUpdateAssemblies: ["GameLogic", "HotUpdate"]
//   hotUpdateAssemblyDefinitions: [GameLogic.asmdef]  // "GameLogic" duplicated
// FilterHotFixAssemblies throws: "hot update assembly:GameLogic is duplicated"

// fix — keep GameLogic in only one list:
//   hotUpdateAssemblies: ["HotUpdate"]
//   hotUpdateAssemblyDefinitions: [GameLogic.asmdef]

// programmatic dedup guard before build:
var combined = new HashSet<string>(StringComparer.Ordinal);
foreach (var name in allNames.Where(n => !string.IsNullOrWhiteSpace(n)))
    if (!combined.Add(name))
        Debug.LogWarning($"Duplicate hot-update assembly will be removed: {name}");
Defensive patterns

Strategy: validation

Validate before calling

var names = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved;
var seen = new HashSet<string>(StringComparer.Ordinal);
foreach (var name in names.Where(n => !string.IsNullOrWhiteSpace(n)))
{
    if (!seen.Add(name))
    {
        Debug.LogError($"Duplicate hot-update assembly name detected: '{name}'. " +
            "Check both hotUpdateAssemblies and hotUpdateAssemblyDefinitions for overlap.");
    }
}

Type guard

static bool HasNoDuplicates(string[] names)
{
    var clean = names.Where(n => !string.IsNullOrWhiteSpace(n));
    return clean.Count() == new HashSet<string>(clean, StringComparer.Ordinal).Count;
}

Try / catch

try
{
    BuildPipeline.BuildPlayer(scenes, outputPath, buildTarget, buildOptions);
}
catch (BuildFailedException ex) when (ex.Message.Contains("is duplicated"))
{
    Debug.LogError("A hot-update assembly name is listed more than once. " +
        "Check hotUpdateAssemblies and hotUpdateAssemblyDefinitions for duplicates.");
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/3851a6c3e1769fd5. Report an issue: GitHub.