Unity-Technologies/UnityCsReference · error · ArgumentException
Target Prefab has to be a Prefab Asset
Error message
Target Prefab has to be a Prefab Asset
What it means
Thrown by AddGameObjectsToPrefabAndConnect when `targetPrefab` is not null but is not itself a Prefab Asset (PrefabUtility.IsPartOfPrefabAsset returns false). The target must be an asset stored on disk, not a scene instance or a plain GameObject.
Source
Thrown at Editor/Mono/Prefabs/PrefabUtility.bindings.cs:283
extern private static GameObject SaveAsPrefabAssetAndConnect_Internal([NotNull] GameObject root, string path, out bool success);
[StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)]
[NativeMethod(ThrowsException = true)]
extern private static GameObject SavePrefabAsset_Internal([NotNull] GameObject root, out bool success);
internal static void AddGameObjectsToPrefabAndConnect(GameObject[] gameObjects, Object targetPrefab)
{
if (gameObjects == null)
throw new ArgumentNullException("gameObjects");
if (gameObjects.Length == 0)
throw new ArgumentException("gameObjects array is empty");
if (targetPrefab == null)
throw new ArgumentNullException("targetPrefab");
if (!PrefabUtility.IsPartOfPrefabAsset(targetPrefab))
throw new ArgumentException("Target Prefab has to be a Prefab Asset");
Object targetPrefabInstance = null;
var targetPrefabObject = PrefabUtility.GetPrefabAssetHandle(targetPrefab);
foreach (GameObject go in gameObjects)
{
if (go == null)
throw new ArgumentException("GameObject in input 'gameObjects' array is null");
if (EditorUtility.IsPersistent(go)) // Prefab asset
throw new ArgumentException("Game object is part of a prefab");
var parentPrefabInstance = GetParentPrefabInstance(go);
if (parentPrefabInstance == null)
throw new ArgumentException("GameObject is not (directly) parented under a target Prefab instance.");
if (targetPrefabInstance == null)View on GitHub (pinned to 225b0fbdb5)
Solutions
- Pass the Prefab Asset root from the Project window, e.g. loaded via AssetDatabase.LoadAssetAtPath<GameObject>.
- Verify with PrefabUtility.IsPartOfPrefabAsset(targetPrefab) before calling.
- If you only have an instance, resolve its source asset via PrefabUtility.GetCorrespondingObjectFromSource / GetPrefabAssetHandle and pass that.
Example fix
// before
GameObject target = Selection.activeGameObject; // a scene instance
PrefabUtility.AddGameObjectsToPrefabAndConnect(gos, target); // throws
// after
GameObject target = Selection.activeGameObject;
if (!PrefabUtility.IsPartOfPrefabAsset(target))
target = PrefabUtility.GetCorrespondingObjectFromSource(target);
if (!PrefabUtility.IsPartOfPrefabAsset(target))
throw new ArgumentException("Target is not a prefab asset.");
PrefabUtility.AddGameObjectsToPrefabAndConnect(gos, target); Defensive patterns
Strategy: validation
Validate before calling
if (targetPrefab == null || !PrefabUtility.IsPartOfPrefabAsset(targetPrefab))
throw new ArgumentException("Target must be a prefab asset on disk.", nameof(targetPrefab)); Type guard
static bool IsPrefabAsset(GameObject obj) => obj != null && PrefabUtility.IsPartOfPrefabAsset(obj);
Prevention
- Resolve targets from the Project window or AssetDatabase.LoadAssetAtPath, not from scene instances.
- Wrap IsPartOfPrefabAsset in a guard helper and use it at every call site.
- If only an instance is available, resolve the source asset via GetCorrespondingObjectFromSource first.
When it happens
Trigger: Passing a scene instance of a prefab, a disconnected prefab instance, a regular non-prefab GameObject, or a prefab that is an instance/variant-in-scene rather than the asset root.
Common situations: Grabbing the target via Selection.activeGameObject while a scene instance (not the asset) is selected. Using the root of an open Prefab edit stage incorrectly. Passing a PrefabAssetHandle/Component instead of the prefab GameObject asset.
Related errors
- gameObjects
- gameObjects array is empty
- targetPrefab
- GameObject in input 'gameObjects' array is null
- Game object is part of a prefab
AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13).
Data as JSON: /api/errors/cc222fb552442f8a.
Report an issue: GitHub.