Unity-Technologies/UnityCsReference · error · ArgumentException

Must be a persistent asset.

Error message

Must be a persistent asset.

What it means

ArgumentException thrown by ValidateContainer when EditorUtility.IsPersistent(container) returns false. This guard ensures the AudioRandomContainer is a saved asset (e.g. a .asset file in the project) rather than a scene-bound or transient instance, because the undo and element-adding operations rely on asset persistence.

Source

Thrown at Editor/Mono/Audio/AudioRandomContainerExtensions.cs:58

            throw new ArgumentNullException(nameof(clips));

        if (clips.Length == 0)
            throw new ArgumentException("Must not be empty.", nameof(clips));

        AddElementsInner(container, clips.Length, (i, element) =>
        {
            if (clips[i] != null)
                element.audioClip = clips[i];
        });
    }

    static void ValidateContainer(AudioRandomContainer container)
    {
        if (container == null)
            throw new ArgumentNullException(nameof(container));

        if (!EditorUtility.IsPersistent(container))
            throw new ArgumentException("Must be a persistent asset.", nameof(container));
    }

    static void AddElementsInner(AudioRandomContainer container, int count,
        Action<int, AudioContainerElement> configureElement)
    {
        var undoGroupName = count > 1 ? $"{k_BaseAddElementsUndoName}s" : k_BaseAddElementsUndoName;

        Undo.RegisterCompleteObjectUndo(container, undoGroupName);
        Undo.SetCurrentGroupName(undoGroupName);

        if (container.elements == null)
            container.elements = Array.Empty<AudioContainerElement>();

        var newElements = new AudioContainerElement[count];
        var oldAndNewElements = new AudioContainerElement[container.elements.Length + count];
        Array.Copy(container.elements, oldAndNewElements, container.elements.Length);

        for (var i = 0; i < count; i++)

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Ensure the AudioRandomContainer is saved as a project asset (Create > Audio > Audio Random Container or via AssetDatabase.CreateAsset).
  2. If the container is scene-based, refactor it to be a persistent asset referenced by the scene.
  3. Verify with EditorUtility.IsPersistent(container) before calling AddElements.
  4. Check that AssetDatabase.Contains(container) returns true for the target.

Example fix

// before — container is a scene instance
container.AddElements(clips);
// after — verify persistence first
if (!EditorUtility.IsPersistent(container))
{
    Debug.LogError("AudioRandomContainer must be a saved asset, not a scene instance.");
    return;
}
container.AddElements(clips);
Defensive patterns

Strategy: validation

Validate before calling

// Verify container is a persistent asset before calling AddElements
if (container != null && EditorUtility.IsPersistent(container))
    container.AddElements(clips);
else
    Debug.LogError("AudioRandomContainer must be a saved project asset.");

Type guard

static bool IsPersistentContainer(AudioRandomContainer container)
    => container != null && EditorUtility.IsPersistent(container);

Prevention

When it happens

Trigger: Calling AddElements on an AudioRandomContainer that exists only in a scene (not saved as a project asset), or on a runtime-instantiated container. EditorUtility.IsPersistent returns false for scene objects and ephemeral instances.

Common situations: Attempting to edit a container that lives in a scene instead of as a ScriptableObject asset, working with runtime-created instances in editor tooling, prefab-embedded containers that are not yet saved as assets, mistaken assumptions about where the container resides.

Related errors


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