Unity-Technologies/UnityCsReference · error · InvalidOperationException

Input '{0}' is not a plain GameObject, it is already a Prefa

Error message

Input '{0}' is not a plain GameObject, it is already a Prefab instance. Use ReplacePrefabAssetOfPrefabInstance() instead.

What it means

Thrown by ThrowIfInvalidArgumentsForConvertToPrefabInstance when IsPartOfNonAssetPrefabInstance(plainGameObject) returns true. ConvertToPrefabInstance expects a plain scene GameObject — one that is NOT already a Prefab instance. If the object is already a Prefab instance, the correct API is ReplacePrefabAssetOfPrefabInstance(), which swaps the underlying asset.

Source

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

            if (!success)
            {
                Debug.LogError(string.Format("Replace Prefab Instance failed for instance '{0}' using asset '{1}' at '{2}'", prefabInstanceRoot.name, prefabAssetRoot.name, AssetDatabase.GetAssetPath(prefabAssetRoot)), prefabInstanceRoot);
            }

            if (mode == InteractionMode.UserAction)
                Undo.FlushTrackedObjects();
        }

        internal static void ThrowIfInvalidArgumentsForConvertToPrefabInstance(GameObject plainGameObject, GameObject prefabAssetRoot, bool checkValidAsset, InteractionMode mode)
        {
            if (plainGameObject == null)
                throw new ArgumentNullException(nameof(plainGameObject));

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

            if (IsPartOfNonAssetPrefabInstance(plainGameObject))
                throw new InvalidOperationException(string.Format("Input '{0}' is not a plain GameObject, it is already a Prefab instance. Use ReplacePrefabAssetOfPrefabInstance() instead.", plainGameObject.name));

            if (EditorUtility.IsPersistent(plainGameObject))
                throw new ArgumentException("Input is from a Prefab asset, this is not supported. Input GameObject: " + plainGameObject.name, nameof(plainGameObject));

            if (checkValidAsset)
                ThrowIfInvalidAssetForReplacePrefabInstance(prefabAssetRoot, mode);

            if (plainGameObject.transform.GetType() != prefabAssetRoot.transform.GetType())
                throw new InvalidOperationException(string.Format("Cannot convert the GameObject '{0}' with root transform of type {1} with a Prefab asset with root transform of type {2}. Transform types must match.", plainGameObject.name, plainGameObject.transform.GetType().Name, prefabAssetRoot.transform.GetType().Name));

            // Prefab Mode and EditPrefabContents scope handling
            if (PrefabStageUtility.IsGameObjectThePrefabRootInAnyPrefabStage(plainGameObject) || (EditorSceneManager.IsPreviewSceneObject(plainGameObject) && plainGameObject.transform.parent == null))
                throw new InvalidOperationException("Replacing the root GameObject in a Prefab with a Prefab instance is not supported since it will break all overrides for existing instances of this Prefab, including their positions and rotations." + plainGameObject.name);

            if (plainGameObject.hideFlags.HasFlag(HideFlags.DontSaveInEditor) || plainGameObject.transform.hideFlags.HasFlag(HideFlags.DontSaveInEditor))
                throw new ArgumentException("Input GameObject is using the HideFlags.DontSaveInEditor flag which is not supported when converting to Prefab instance: GameObject: " + plainGameObject.name, nameof(plainGameObject));

            if (mode == InteractionMode.UserAction)

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. If the object is already a Prefab instance, call PrefabUtility.ReplacePrefabAssetOfPrefabInstance() instead.
  2. Guard with: if (PrefabUtility.IsPartOfNonAssetPrefabInstance(obj)) call Replace; else call Convert.
  3. Unpack the Prefab instance (UnpackPrefabInstance) first if you truly need to re-convert.

Example fix

// before
PrefabUtility.ConvertToPrefabInstance(myGo, prefabAsset, settings, mode);
// myGo is already a Prefab instance

// after
if (PrefabUtility.IsPartOfNonAssetPrefabInstance(myGo))
    PrefabUtility.ReplacePrefabAssetOfPrefabInstance(myGo, prefabAsset, mode);
else
    PrefabUtility.ConvertToPrefabInstance(myGo, prefabAsset, settings, mode);
Defensive patterns

Strategy: validation

Validate before calling

if (PrefabUtility.IsPartOfNonAssetPrefabInstance(plainGameObject))
{
    PrefabUtility.ReplacePrefabAssetOfPrefabInstance(plainGameObject, prefabAssetRoot, mode);
    return;
}
PrefabUtility.ConvertToPrefabInstance(plainGameObject, prefabAssetRoot, settings, mode);

Type guard

static bool IsPlainSceneGameObject(GameObject obj)
{
    return obj != null
        && !PrefabUtility.IsPartOfNonAssetPrefabInstance(obj)
        && !EditorUtility.IsPersistent(obj);
}

Prevention

When it happens

Trigger: Calling ConvertToPrefabInstance on a GameObject that was already instantiated from a Prefab (i.e. it is a Prefab instance). E.g. a scene object created via Instantiate(prefabAsset) passed to ConvertToPrefabInstance.

Common situations: Generic 'apply Prefab' code that doesn't distinguish plain GameObjects from existing instances. Re-running a conversion script on objects that were already converted in a previous pass.

Related errors


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