Unity-Technologies/UnityCsReference · error · InvalidOperationException
Asset {objectToAdd} has a non-null path. Build profile compo
Error message
Asset {objectToAdd} has a non-null path. Build profile components should be sub-assets. What it means
Thrown by BuildProfile.AddComponent<T> when the object to add already has a non-empty asset path (AssetDatabase.GetAssetPath returns a path). Build profile components must be sub-assets of the profile asset itself, not independent assets referenced by path. The code path that handles empty assetPath adds the object as a sub-asset and returns; otherwise it throws InvalidOperationException, noting a future API will support reference-style components.
Source
Thrown at Editor/Mono/BuildProfile/BuildProfile.API.cs:127
}
// Don't allow duplicates
var found = GetComponent<T>();
if (found != null)
{
throw new ArgumentException($"The component {typeof(T).Name} already exists in the build profile {name}.");
}
var assetPath = AssetDatabase.GetAssetPath(objectToAdd);
if (string.IsNullOrEmpty(assetPath))
{
objectToAdd.hideFlags |= HideFlags.HideInHierarchy;
AssetDatabase.AddObjectToAsset(objectToAdd, this);
return;
}
// TODO: Future API will support build profile components as reference.
throw new InvalidOperationException($"Asset {objectToAdd} has a non-null path. Build profile components should be sub-assets.");
}
/// <summary>
/// Removes the first occurence of a component of type T from the build profile.
/// </summary>
public void RemoveComponent<T>() where T : UnityEngine.Object
{
var found = GetComponent<T>();
if (found == null)
{
Debug.LogWarning($"The component {typeof(T).Name} does not exist in the build profile {name}. ");
return;
}
if (Array.IndexOf(this.requiredComponents, found) > -1)
throw new ArgumentException($"The component {typeof(T).Name} is required and cannot be removed from the build profile {name}.");
AssetDatabase.RemoveObjectFromAsset(found);View on GitHub (pinned to 225b0fbdb5)
Solutions
- Pass a fresh, unsaved ScriptableObject instance (one with no asset path) so it can be added as a sub-asset.
- If you must use an existing asset, first remove it from its current asset file or create a new instance with ScriptableObject.CreateInstance and copy its data.
- Await/track the future API referenced by the TODO for reference-style components.
Example fix
// before
var existing = AssetDatabase.LoadAssetAtPath<MySettings>("Assets/x.asset");
profile.AddComponent(existing); // has a path -> throws
// after
var fresh = ScriptableObject.CreateInstance<MySettings>();
EditorUtility.CopySerialized(existing, fresh);
profile.AddComponent(fresh); Defensive patterns
Strategy: validation
Validate before calling
if (!string.IsNullOrEmpty(AssetDatabase.GetAssetPath(obj))) { /* has a path; create fresh instead */ } Type guard
static bool IsUnsaved(UnityEngine.Object o) => string.IsNullOrEmpty(AssetDatabase.GetAssetPath(o));
Prevention
- Only pass freshly created ScriptableObject instances to AddComponent.
- Check AssetDatabase.GetAssetPath is empty before adding.
- Copy serialized data from an existing asset to a new instance rather than passing the asset directly.
When it happens
Trigger: Passing an object that is already saved as its own asset (e.g. created via AssetDatabase.CreateAsset) to AddComponent. Because GetAssetPath returns the file path, the method refuses and throws.
Common situations: Loading an existing .asset ScriptableObject and trying to attach it to a profile; re-parenting an asset that was authored standalone in the project; copying/moving components between profiles that were saved independently.
Related errors
- The object {objectToRemove} (path: {objectToRemovePath}) is
- The component {typeof(T).Name} already exists in the build p
- Type {type.Name} is not a ScriptableObject or a supported se
- The object to add cannot be null.
- The component {typeof(T).Name} is required and cannot be rem
AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13).
Data as JSON: /api/errors/e1a1b778694866ff.
Report an issue: GitHub.