Quick answer: One of the two transforms in your SetParent call (or the parent you passed to Instantiate) is the prefab asset, not an object in the scene. Use the instance that Instantiate returns, and check that Inspector fields for parents reference scene objects. Editor scripts should edit prefabs through PrefabUtility.LoadPrefabContents.
This error has the same root cause as most prefab bugs in Unity: a variable you believe holds the spawned copy actually holds the prefab it was spawned from. Unity refuses to restructure the asset at runtime, so you get an error instead of a corrupted prefab.
The exact error
Setting the parent of a transform which resides in a Prefab Asset is disabled to prevent data corruption (GameObject: 'Enemy').
The name in parentheses is the object Unity refused to move.
Cause 1: parenting the prefab instead of the instance
// Wrong: the prefab asset is reparented
Instantiate(enemyPrefab);
enemyPrefab.transform.SetParent(enemiesRoot);
// Right
GameObject enemy = Instantiate(enemyPrefab);
enemy.transform.SetParent(enemiesRoot, false);
// Better: parent in the same call
GameObject enemy = Instantiate(enemyPrefab, enemiesRoot);
Cause 2: the parent field references a prefab
If the object being moved is a fresh instance, the parent may be the asset. A common setup: a UI item prefab is spawned into a “content” transform, and the content field on a prefabbed script was assigned to something inside another prefab asset rather than the instance in the scene. Select the component in the Hierarchy and click the parent field: if it pings an object in the Project window, it is an asset. Reassign it to the scene object, or find it at runtime after spawning.
This often appears after turning a scene object into a prefab: references between objects in the same prefab stay valid, but references from the prefab to scene objects cannot be stored in the asset.
Cause 3: editor scripts
Tools that restructure prefabs must work on loaded prefab contents, not on the asset object from AssetDatabase.LoadAssetAtPath:
GameObject root = PrefabUtility.LoadPrefabContents(path);
Transform socket = root.transform.Find("WeaponSocket");
GameObject sword = (GameObject)PrefabUtility.InstantiatePrefab(swordPrefab);
sword.transform.SetParent(socket, false);
PrefabUtility.SaveAsPrefabAsset(root, path);
PrefabUtility.UnloadPrefabContents(root);
Quick runtime check
static bool IsAsset(Component c) => !c.gameObject.scene.IsValid();
if (IsAsset(parent)) Debug.LogError($"Parent {parent.name} is a prefab asset, not a scene object", parent);
Objects in the Project window have no valid scene; anything in the Hierarchy does.
Prefab reference bugs in builds
In builds these mistakes usually surface as objects spawning at the origin, UI items appearing nowhere, or NullReferenceExceptions further along. Bugnet's Unity SDK hooks Unity's log stream, so exceptions and errors in a player's build are filed automatically with the last log lines, a screenshot, the device, OS and build version, and identical ones stack into a single issue with a count.
Related problems
- How to Fix “Destroying assets is not permitted to avoid data loss” in Unity
- Fix: Unity Prefab Instance Overrides Applied to Asset Accidentally
- How to Fix a “Missing Prefab” in a Unity Scene
Frequently asked questions
What causes “Setting the parent of a transform which resides in a Prefab Asset is disabled”?
SetParent was called on a prefab asset, or with a prefab asset as the parent, instead of on scene instances. Use the object returned by Instantiate and scene references for parents.
How do I instantiate a prefab under a parent in Unity?
Pass the parent to Instantiate, for example Instantiate(prefab, parentTransform), or call SetParent on the returned instance.
How do I change a prefab’s hierarchy from an editor script?
Use PrefabUtility.LoadPrefabContents, modify the loaded objects, save with SaveAsPrefabAsset and call UnloadPrefabContents.
If the Inspector field pings the Project window, it is an asset, and you cannot parent things to it at runtime.