Unity-Technologies/UnityCsReference · error · ArgumentException
Object to create variant from has to be a Prefab root
Error message
Object to create variant from has to be a Prefab root
What it means
PrefabUtility.CreateVariant checks that the provided assetRoot is the root of its prefab (assetRoot.transform.root.gameObject == assetRoot) and throws ArgumentException('Object to create variant from has to be a Prefab root') otherwise. Variants must be created from the top-level GameObject of the prefab file; passing a child object within the prefab hierarchy is not allowed.
Source
Thrown at Editor/Mono/Prefabs/PrefabUtility.bindings.cs:234
// Resets the properties of all objects in the prefab, including child game objects and components that were added to the prefab instance
[NativeMethod("RevertPrefabInstance", IsFreeFunction = true)]
extern private static bool RevertPrefabInstance_Internal([NotNull] GameObject go);
// Helper function to find the prefab root of an object
[FreeFunction]
[Obsolete("Use GetOutermostPrefabInstanceRoot if source is a Prefab instance or source.transform.root.gameObject if source is a Prefab Asset object.")]
extern public static GameObject FindPrefabRoot([NotNull] GameObject source);
internal static GameObject CreateVariant(GameObject assetRoot, string path)
{
if (assetRoot == null)
throw new ArgumentNullException("The inputObject is null");
if (!IsPartOfPrefabAsset(assetRoot))
throw new ArgumentException("Given input object is not a prefab asset");
if (assetRoot.transform.root.gameObject != assetRoot)
throw new ArgumentException("Object to create variant from has to be a Prefab root");
if (path == null)
throw new ArgumentNullException("The path is null");
var assetRootObjectPath = AssetDatabase.GetAssetPath(assetRoot);
if (Paths.AreEqual(path, assetRootObjectPath, true))
throw new ArgumentException("Creating a variant of an object into the source file of the input object is not allowed");
if (!Paths.IsValidAssetPath(path, ".prefab"))
throw new ArgumentException("Given path is not valid: '" + path + "'");
return CreateVariant_Internal(assetRoot, path);
}
[NativeMethod("CreateVariant", IsFreeFunction = true)]
extern private static GameObject CreateVariant_Internal([NotNull] GameObject original, string path);
[StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)]View on GitHub (pinned to 225b0fbdb5)
Solutions
- Navigate to the prefab root before calling CreateVariant: assetRoot = assetRoot.transform.root.gameObject
- If starting from a child, use go.transform.root.gameObject to get the root
- Verify with PrefabUtility.GetOutermostPrefabInstanceRoot or check that the object has no parent in the prefab hierarchy
Example fix
// before
var variant = PrefabUtility.CreateVariant(childObject, "Assets/Variant.prefab");
// after
GameObject root = childObject.transform.root.gameObject;
if (PrefabUtility.IsPartOfPrefabAsset(root) && root.transform.root.gameObject == root)
var variant = PrefabUtility.CreateVariant(root, "Assets/Variant.prefab"); Defensive patterns
Strategy: validation
Validate before calling
GameObject root = assetRoot.transform.root.gameObject;
if (root != assetRoot)
{
Debug.LogError("CreateVariant requires the prefab root, not a child object.");
return;
}
// Safe to call CreateVariant(root, path) Type guard
static bool IsPrefabRoot(GameObject go) =>
go != null && PrefabUtility.IsPartOfPrefabAsset(go) && go.transform.root.gameObject == go; Try / catch
try { var variant = PrefabUtility.CreateVariant(assetRoot, path); }
catch (ArgumentException ex) when (ex.Message == "Object to create variant from has to be a Prefab root")
{ Debug.LogError($"{assetRoot.name} is not the prefab root. Use transform.root.gameObject."); } Prevention
- Always navigate to transform.root.gameObject before calling CreateVariant
- Validate that the object is the root of its prefab hierarchy
- When processing user-selected child objects, resolve the root first
When it happens
Trigger: Calling CreateVariant with a child GameObject of a prefab asset (e.g., a nested component or sub-object) instead of the prefab's root. Code that passes a specific child found via transform.Find or GetComponentInChildren without navigating to the root first.
Common situations: Editor tools that operate on a user-selected child object within a prefab. Code that searches for a specific component and then tries to create a variant from the component's GameObject. Prefab nesting where the code mistakenly grabs a nested prefab child.
Related errors
- Given input object is not a prefab asset
- Provided GameObject is not a Prefab instance
- The inputObject is null
- PersistentLocalStorageSize must be between 256 and 4096, but
- guid
AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13).
Data as JSON: /api/errors/d08d5f7222acc126.
Report an issue: GitHub.