Unity-Technologies/UnityCsReference · error · ArgumentException
The component {typeof(T).Name} already exists in the build p
Error message
The component {typeof(T).Name} already exists in the build profile {name}. What it means
Thrown by BuildProfile.CreateComponent<T>() when a sub-asset component of the same type T already exists on the build profile. Unity's BuildProfile enforces a one-component-per-type invariant, so attempting to create a duplicate is rejected with an ArgumentException. The check delegates to GetComponent<T>() first, and only creates a new ScriptableObject instance if none is found.
Source
Thrown at Editor/Mono/BuildProfile/BuildProfile.API.cs:54
return;
BuildProfileModuleUtil.SwitchLegacyActiveFromBuildProfile(buildProfile);
}
/// <summary>
/// Instantiates a new component of type T and adds it as a sub-asset to the build profile.
/// </summary>
/// <returns>Returns the newly created ScriptableObect.</returns>
/// <exception cref="ArgumentException">
/// Thrown when a sub asset of the same type already exists in the build profile.
/// </exception>
[VisibleToOtherModules]
public T CreateComponent<T>() where T : UnityEngine.Object
{
var found = GetComponent<T>();
if (found != null)
{
throw new ArgumentException($"The component {typeof(T).Name} already exists in the build profile {name}.");
}
var type = typeof(T);
if (type.IsSubclassOf(typeof(ScriptableObject)))
{
var objectToAdd = ScriptableObject.CreateInstance(type);
objectToAdd.hideFlags = HideFlags.HideInHierarchy;
objectToAdd.name = type.Name;
AssetDatabase.AddObjectToAsset(objectToAdd, this);
return objectToAdd as T;
}
throw new ArgumentException($"Type {type.Name} is not a ScriptableObject or a supported settings object type.");
}
/// <summary>
/// Gets a component of type T associated with the build profile, its global fallback,
/// or null if the component is not available.View on GitHub (pinned to 225b0fbdb5)
Solutions
- Call GetComponent<T>() first and only call CreateComponent<T>() when it returns null.
- If you intend to replace, call RemoveComponent<T>() (or ForceRemoveComponent<T>() for required components) before CreateComponent<T>().
- Audit the calling code to prevent the CreateComponent call from running more than once per profile (e.g. guard with a flag or existence check).
Example fix
// before
profile.CreateComponent<MySettings>();
// after
if (profile.GetComponent<MySettings>() == null)
profile.CreateComponent<MySettings>(); Defensive patterns
Strategy: validation
Validate before calling
if (profile.GetComponent<T>() != null) { /* already exists; skip or replace */ } Type guard
static bool HasComponent<P,T>(P profile) where P : BuildProfile where T : UnityEngine.Object => profile.GetComponent<T>() != null;
Prevention
- Always call GetComponent<T>() before CreateComponent<T>().
- Make profile initialization idempotent so it never runs twice.
- Centralize component creation in one setup method.
When it happens
Trigger: Calling CreateComponent<T>() when GetComponent<T>() already returns a non-null instance for the same type T on the same BuildProfile. Common when initialization code runs twice or a component was created via AddComponent or deserialization previously.
Common situations: Re-running editor setup/initialization scripts that create components without checking existence first; migrating build profiles that already carry deserialized components; calling CreateComponent inside a loop or repeated editor callback.
Related errors
- Type {type.Name} is not a ScriptableObject or a supported se
- The component {typeof(T).Name} is required and cannot be rem
- The object {objectToRemove} (path: {objectToRemovePath}) is
- Cannot create build profile for '{platformName}' (GUID: {pla
- Platform GUID {platformGuid} is not a valid Unity build plat
AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13).
Data as JSON: /api/errors/c18dd24fdabf9aff.
Report an issue: GitHub.