Unity-Technologies/UnityCsReference · error · ArgumentException

GameObject to save Prefab from must be a Prefab root

Error message

GameObject to save Prefab from must be a Prefab root

What it means

SavePrefabAsset operates on whole prefabs, so the supplied asset must be the root of its prefab. If asset.transform.root.gameObject != asset, the caller passed a non-root child and ArgumentException is thrown. The method then forwards the root to the internal save routine.

Source

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

        public static GameObject SavePrefabAsset(GameObject asset, out bool savedSuccessfully)
        {
            if (asset == null)
                throw new ArgumentNullException("Parameter prefabAssetGameObject is null");

            // Include model check even though models are also immutable, since we can give a more clear exception message.
            if (IsPartOfModelPrefab(asset))
                throw new ArgumentException("Can't save a Model Prefab");

            if (IsPartOfImmutablePrefab(asset))
                throw new ArgumentException("Can't save an immutable Prefab");

            string path = AssetDatabase.GetAssetPath(asset);
            if (String.IsNullOrEmpty(path))
                throw new ArgumentException("Can't save a Prefab instance");

            var root = asset.transform.root.gameObject;
            if (root != asset)
                throw new ArgumentException("GameObject to save Prefab from must be a Prefab root");

            return SavePrefabAsset_Internal(root, out savedSuccessfully);
        }

        internal static void ValidatePath(GameObject instanceRoot, string path)
        {
            if (String.IsNullOrEmpty(path))
                throw new ArgumentNullException("path is null or empty");

            if (!Paths.IsValidAssetPath(path, ".prefab"))
                throw new ArgumentException("Given path is not valid: '" + path + "'");

            if (Directory.Exists(path))
                throw new ArgumentException("Overwriting a folder with an Asset is not allowed: '" + path + "'");

            string directory = Path.GetDirectoryName(path);

            // We allow relative paths outside the Assets folder so we do not throw if isValidAssetFolder is false

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Resolve the root before saving: asset = asset.transform.root.gameObject.
  2. Filter selection to root objects, or walk up to the root explicitly.
  3. Verify asset.transform.root.gameObject == asset before calling.

Example fix

// before
PrefabUtility.SavePrefabAsset(childGo);

// after
PrefabUtility.SavePrefabAsset(childGo.transform.root.gameObject);
Defensive patterns

Strategy: validation

Validate before calling

GameObject root = asset.transform.root.gameObject;
if (root != asset) asset = root;

Type guard

static bool IsPrefabRoot(GameObject asset) =>
    asset != null && asset.transform.root.gameObject == asset;

Prevention

When it happens

Trigger: Passing a child GameObject of a prefab asset rather than the prefab root.

Common situations: Selecting a child object within a prefab asset and calling save; selection logic that hands back a sub-object instead of the root.

Related errors


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