Unity-Technologies/UnityCsReference · error · InvalidOperationException

Replacing the root Prefab instance in a Variant is not suppo

Error message

Replacing the root Prefab instance in a Variant is not supported since it will break all overrides for existing instances of this Variant, including their positions and rotations.

What it means

Thrown by ThrowIfInvalidArgumentsForReplacePrefabInstance when PrefabStageUtility.IsGameObjectThePrefabRootInAnyPrefabStage(prefabInstanceRoot) is true. This means the object is the root being edited inside an open Prefab Stage (Prefab Mode). Replacing the root of a Prefab/Variant being edited would silently destroy all overrides on downstream instances, so Unity blocks it.

Source

Thrown at Editor/Mono/Prefabs/PrefabUtility.cs:2257

            if (prefabInstanceRoot == null)
                throw new ArgumentNullException(nameof(prefabInstanceRoot));

            if (prefabAssetRoot == null)
                throw new ArgumentNullException(nameof(prefabAssetRoot));

            if (checkValidAsset)
                ThrowIfInvalidAssetForReplacePrefabInstance(prefabAssetRoot, mode);

            if (!IsPartOfNonAssetPrefabInstance(prefabInstanceRoot))
                throw new InvalidOperationException(string.Format("Input '{0}' is not a Prefab instance, for plain GameObjects use ConvertToPrefabInstance() instead", prefabInstanceRoot.name));

            if (!IsOutermostPrefabInstanceRoot(prefabInstanceRoot))
                throw new ArgumentException("Input instance is not an outermost Prefab instance root. Input instance: " + prefabInstanceRoot.name, nameof(prefabInstanceRoot));
            if (EditorUtility.IsPersistent(prefabInstanceRoot))
                throw new ArgumentException("Input instance root is from a Prefab asset, this is not supported. Input instance: " + prefabInstanceRoot.name, nameof(prefabInstanceRoot));

            if (PrefabStageUtility.IsGameObjectThePrefabRootInAnyPrefabStage(prefabInstanceRoot))
                throw new InvalidOperationException("Replacing the root Prefab instance in a Variant is not supported since it will break all overrides for existing instances of this Variant, including their positions and rotations." + prefabInstanceRoot.name);
            if (IsAnyPrefabInstanceRoot(prefabInstanceRoot) && EditorSceneManager.IsPreviewSceneObject(prefabInstanceRoot) && prefabInstanceRoot.transform.parent == null) // EditPrefabContentsScope handling
                throw new InvalidOperationException("Replacing the Variant parent is not supported since it will break all overrides for existing instances of this Variant, including their positions and rotations." + prefabInstanceRoot.name);
            if (prefabInstanceRoot.transform.GetType() != prefabAssetRoot.transform.GetType())
                throw new InvalidOperationException(string.Format("Cannot replace the Prefab instance '{0}' with root transform of type {1} with a Prefab asset with root transform of type {2}. Transform types must match.", prefabInstanceRoot.name, prefabInstanceRoot.transform.GetType().Name, prefabAssetRoot.transform.GetType().Name));

            if (prefabInstanceRoot.hideFlags.HasFlag(HideFlags.DontSaveInEditor) || prefabInstanceRoot.transform.hideFlags.HasFlag(HideFlags.DontSaveInEditor))
                throw new ArgumentException("Input instance root is using the HideFlags.DontSaveInEditor flag which is not supported when replacing: Input instance: " + prefabInstanceRoot.name, nameof(prefabInstanceRoot));

            if (mode == InteractionMode.UserAction)
            {
                // Recording undo does not handle missing scripts
                var gameObjectsWithInvalidScript = FindGameObjectsWithInvalidComponent(prefabInstanceRoot);
                if (gameObjectsWithInvalidScript.Count > 0)
                    throw new InvalidOperationException(string.Format($"Cannot replace the Prefab instance when it has a missing script. GameObject '{gameObjectsWithInvalidScript[0].name}' has a missing script. Use InteractionMode.AutomatedAction to force the replace."));
            }
        }

        public static void ReplacePrefabAssetOfPrefabInstances(GameObject[] prefabInstanceRoots, GameObject prefabAssetRoot, InteractionMode mode)

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Close the Prefab Stage (StageUtility.GoToMainStage) before calling ReplacePrefabAssetOfPrefabInstance.
  2. Guard with: if (PrefabStageUtility.IsGameObjectThePrefabRootInAnyPrefabStage(obj)) return;
  3. Edit the Prefab asset contents via PrefabUtility.LoadPrefabContents and operate there instead of in a live Stage.

Example fix

// before
PrefabUtility.ReplacePrefabAssetOfPrefabInstance(stageRootGo, prefabAsset, mode);

// after
StageUtility.GoToMainStage(); // close the open Prefab Stage first
PrefabUtility.ReplacePrefabAssetOfPrefabInstance(stageRootGo, prefabAsset, mode);
Defensive patterns

Strategy: validation

Validate before calling

if (PrefabStageUtility.IsGameObjectThePrefabRootInAnyPrefabStage(prefabInstanceRoot))
{
    StageUtility.GoToMainStage(); // close the Prefab Stage
}
PrefabUtility.ReplacePrefabAssetOfPrefabInstance(prefabInstanceRoot, prefabAssetRoot, mode);

Type guard

static bool IsSafeToReplace(GameObject obj)
{
    return obj != null
        && !PrefabStageUtility.IsGameObjectThePrefabRootInAnyPrefabStage(obj);
}

Prevention

When it happens

Trigger: User opens a Variant Prefab in Prefab Mode (double-click to edit) and a script then calls ReplacePrefabAssetOfPrefabInstance on the Prefab Stage root. Automated build pipeline that opens Prefab Stage via PrefabStageUtility and tries to swap the root.

Common situations: Editor scripts triggered by PostProcessScene or scene-save callbacks while a Prefab Stage is open. Batch operations that don't check whether the current selection is inside a Prefab Stage.

Related errors


AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13). Data as JSON: /api/errors/c6ab4f1315d2c770. Report an issue: GitHub.