Unity-Technologies/UnityCsReference · error · ArgumentNullException

Prefab instance must not be null.

Error message

Prefab instance must not be null.

What it means

Thrown by ApplyRemovedGameObject when PrefabUtility.GetPrefabInstanceHandle(gameObjectInInstance) returns null. This means gameObjectInInstance is not actually part of a prefab instance in the open scene, so there is no instance handle to apply the removal override onto. The library refuses to proceed because applying a removal requires a live prefab instance context.

Source

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

        public static void ApplyRemovedGameObject(GameObject gameObjectInInstance, GameObject assetGameObject, InteractionMode action)
        {
            DateTime startTime = DateTime.UtcNow;

            ThrowExceptionIfNotValidPrefabInstanceObject(gameObjectInInstance, true);

            if (assetGameObject == null)
                throw new ArgumentNullException(nameof(assetGameObject), "Prefab source must not be null.");
            if (!IsPrefabInstanceObjectOf(gameObjectInInstance, PrefabUtility.GetPrefabAssetHandle(assetGameObject)))
                throw new ArgumentException("Prefab instance must match Prefab source.");
            if (assetGameObject.transform.root == assetGameObject.transform)
                throw new ArgumentException("The asset GameObject cannot be the root as the root cannot be removed as an override.");

            var actionName = "Apply Prefab removed GameObject";
            var prefabInstanceObject = PrefabUtility.GetPrefabInstanceHandle(gameObjectInInstance);
            GameObject prefabInstanceRoot = GetOutermostPrefabInstanceRoot(gameObjectInInstance);

            if (prefabInstanceObject == null)
                throw new ArgumentNullException(nameof(prefabInstanceObject), "Prefab instance must not be null.");

            PrefabUtility.Internal_CallPrefabInstanceApplying(prefabInstanceRoot);

            string assetPath = AssetDatabase.GetAssetPath(assetGameObject);
            GameObject assetRoot = GetRootGameObject(assetGameObject);
            byte[] originalFileContent = null;

            if (action == InteractionMode.UserAction)
            {
                if (!FileUtil.ReadFileContentBinary(assetPath, out originalFileContent, out string errorMessage))
                    Debug.LogError($"No undo was registered when removing GameObject {assetGameObject.name} from {assetRoot.name}. \nError: {errorMessage}", assetRoot);
            }

            using (var scope = new EditPrefabContentsScope(assetPath))
            {
                var assetGOId = Unsupported.GetFileIDHint(assetGameObject);
                var transformsInAsset = scope.prefabContentsRoot.GetComponentsInChildren(typeof(Transform), true);

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Guard the call with PrefabUtility.GetOutermostPrefabInstanceRoot(gameObjectInInstance) != null before invoking.
  2. Ensure gameObjectInInstance is a child of a prefab instance, not a disconnected prefab or a plain GameObject.
  3. When batching, filter out nulls and non-prefab objects (check IsPartOfPrefabInstance) before applying.

Example fix

// before
PrefabUtility.ApplyRemovedGameObject(goInInstance, assetGo, InteractionMode.UserAction);

// after
if (PrefabUtility.GetOutermostPrefabInstanceRoot(goInInstance) != null)
    PrefabUtility.ApplyRemovedGameObject(goInInstance, assetGo, InteractionMode.UserAction);
Defensive patterns

Strategy: validation

Validate before calling

if (gameObjectInInstance == null) return false;
var root = PrefabUtility.GetOutermostPrefabInstanceRoot(gameObjectInInstance);
if (root == null) return false;
var handle = PrefabUtility.GetPrefabInstanceHandle(gameObjectInInstance);
return handle != null;

Type guard

static bool IsValidPrefabInstanceObject(GameObject go) =>
    go != null && PrefabUtility.GetOutermostPrefabInstanceRoot(go) != null
    && PrefabUtility.GetPrefabInstanceHandle(go) != null;

Prevention

When it happens

Trigger: Calling the apply-removed-GameObject path with a gameObjectInInstance that is a plain scene object, a disconnected/broken prefab, or an object whose instance was already reverted/unloaded. Also reachable when the selection contains an object that is not a descendant of any prefab instance root.

Common situations: Iterating a heterogeneous selection that mixes prefab children with loose scene objects; operating on an object whose prefab connection was severed by a prior unpack/revert; batch scripts that do not filter by prefab membership before applying overrides.

Related errors


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