Unity-Technologies/UnityCsReference · error · InvalidOperationException
Cannot start a new build because there is already a build in
Error message
Cannot start a new build because there is already a build in progress.
What it means
InvalidOperationException thrown by BuildPipeline.BuildPlayer(BuildPlayerOptions) when the static isBuildingPlayer flag is already true, indicating a concurrent build is active. Unity does not support parallel or nested build operations; only one build can run at a time in the editor process.
Source
Thrown at Editor/Mono/BuildPipeline/BuildPipeline.bindings.cs:202
///Calling this method will invalidate any variables in the editor script that reference GameObjects, so they will need to be reacquired after the call.
///
///Scripts can run at strategic points during the build by implementing one of the supported callback interfaces, for example <see cref="BuildPlayerProcessor" />, <see cref="IPreprocessBuildWithContext" />, <see cref="IProcessSceneWithReport" /> and <see cref="IPostprocessBuildWithContext" />.
///
///Note: Be aware that changes to [scripting symbols](xref:um-platform-dependent-compilation) only take effect at the next domain reload, when scripts are recompiled.
///
///This means if you make changes to the defined scripting symbols via code using <see cref="PlayerSettings.SetDefineSymbolsForGroup" /> without a domain reload before calling this function, those changes won't take effect.
///
///It also means that the built-in scripting symbols defined for the current active target platform (such as UNITY_STANDALONE_WIN, or UNITY_ANDROID) remain in place even if you try to build for a different target platform, which can result in the wrong code being compiled into your build.</remarks>
///<param name="buildPlayerOptions">Provide various options to control the behavior of <see cref="BuildPipeline.BuildPlayer" />.</param>
///<returns>A <see cref="BuildReport" /> object containing build process information.</returns>
///<example>
/// <code source="../../../Modules/ContentBuild/Tests/local.test.build-examples/Editor/BuildPipeline/BuildPipeline_BuildPlayer.cs"/>
///</example>
///<seealso cref="BuildPlayerWindow.DefaultBuildMethods.BuildPlayer" />
public static BuildReport BuildPlayer(BuildPlayerOptions buildPlayerOptions)
{
if (isBuildingPlayer)
throw new InvalidOperationException("Cannot start a new build because there is already a build in progress.");
if (buildPlayerOptions.targetGroup == BuildTargetGroup.Unknown)
buildPlayerOptions.targetGroup = GetBuildTargetGroup(buildPlayerOptions.target);
string locationPathNameError;
if (!ValidateLocationPathNameForBuildTarget(buildPlayerOptions.locationPathName, buildPlayerOptions.target, buildPlayerOptions.subtarget, buildPlayerOptions.options, out locationPathNameError))
throw new ArgumentException(locationPathNameError);
string scenesError;
if (!ValidateScenePaths(buildPlayerOptions.scenes, out scenesError))
throw new ArgumentException(scenesError);
if ((buildPlayerOptions.options & BuildOptions.AcceptExternalModificationsToPlayer) == BuildOptions.AcceptExternalModificationsToPlayer)
{
CanAppendBuild canAppend = BuildCanBeAppended(buildPlayerOptions.target, buildPlayerOptions.locationPathName);
if (canAppend == CanAppendBuild.Unsupported)
throw new InvalidOperationException("The build target does not support build appending.");
if (canAppend == CanAppendBuild.No)View on GitHub (pinned to 225b0fbdb5)
Solutions
- Check BuildPipeline.isBuildingPlayer before calling BuildPlayer and queue or skip if a build is active.
- Subscribe to BuildPlayerWindow.OnBuildStarted/OnBuildEnded or use EditorApplication updates to detect build completion.
- In CI or batch mode, wait for the previous build process to fully exit before starting the next.
- Refactor nested or chained build logic to execute sequentially rather than concurrently.
Example fix
// before
BuildPipeline.BuildPlayer(options1);
BuildPipeline.BuildPlayer(options2); // may overlap
// after
BuildPipeline.BuildPlayer(options1);
// wait for completion (in batch mode, the BuildPlayer call is synchronous)
if (!BuildPipeline.isBuildingPlayer)
BuildPipeline.BuildPlayer(options2); Defensive patterns
Strategy: validation
Validate before calling
// Check build status before starting a new build
if (BuildPipeline.isBuildingPlayer)
{
Debug.LogWarning("A build is already in progress. Skipping or queuing this build.");
return;
}
BuildPipeline.BuildPlayer(buildPlayerOptions); Type guard
static bool CanStartBuild() => !BuildPipeline.isBuildingPlayer;
Try / catch
try
{
BuildPipeline.BuildPlayer(options);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("already a build in progress"))
{
// Queue the build or wait for the current one to finish
Debug.LogWarning(ex.Message);
} Prevention
- Always check BuildPipeline.isBuildingPlayer before calling BuildPlayer.
- Avoid triggering builds from PostBuild callbacks or nested build logic.
- In CI pipelines, ensure each build process fully exits before starting the next.
- Use a build queue or state machine for chained or scheduled builds.
When it happens
Trigger: Calling BuildPipeline.BuildPlayer while another BuildPlayer call is still executing. Occurs in editor scripts that trigger builds from callbacks, continuous integration scripts that retry builds, or asynchronous build orchestration that does not wait for the previous build to finish.
Common situations: PostBuild callbacks that trigger additional builds, CI scripts that invoke builds in rapid succession without checking build status, editor automation that starts a build on a timer or event without checking isBuildingPlayer, async/await patterns where build completion is not awaited.
Related errors
- Build profile is invalid.
- The 'locationPathName' parameter for BuildPipeline.BuildPlay
- For the '{0}' target the 'locationPathName' parameter for Bu
- bindings and keyframes must be of equal length
- bindings and curves must be of equal length
AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13).
Data as JSON: /api/errors/4bbba069e3407f0f.
Report an issue: GitHub.