Unity-Technologies/UnityCsReference · error · InvalidOperationException

The build cannot be appended.

Error message

The build cannot be appended.

What it means

Thrown when BuildPlayer is called with BuildOptions.AcceptExternalModificationsToPlayer on a platform that conceptually supports appending, but the existing export at locationPathName cannot be appended to. BuildCanBeAppended returns CanAppendBuild.No when the target directory is missing, was produced by a different Unity version, or is in an inconsistent state.

Source

Thrown at Editor/Mono/BuildPipeline/BuildPipeline.bindings.cs:221

            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)
                    throw new InvalidOperationException("The build cannot be appended.");
            }

            if (buildPlayerOptions.scenes != null)
            {
                for (int i = 0; i < buildPlayerOptions.scenes.Length; i++)
                    buildPlayerOptions.scenes[i] = buildPlayerOptions.scenes[i].Replace('\\', '/').Replace("//", "/");
            }

            if ((buildPlayerOptions.options & BuildOptions.Development) == 0)
            {
                if ((buildPlayerOptions.options & BuildOptions.AllowDebugging) != 0)
                {
                    throw new ArgumentException("Non-development build cannot allow debugging. Either add the Development build option, or remove the AllowDebugging build option.");
                }

                if ((buildPlayerOptions.options & BuildOptions.EnableCodeCoverage) != 0)
                {
                    throw new ArgumentException("Non-development build cannot allow code coverage. Either add the Development build option, or remove the EnableCodeCoverage build option.");

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Delete the existing export directory and do a clean export (first append to a fresh location always succeeds).
  2. Verify the locationPathName points to a valid prior export created by the same Unity version before enabling AcceptExternalModificationsToPlayer.
  3. In CI, run a full clean build on the first run of a new Unity version, then switch to incremental for subsequent runs.

Example fix

// before
var options = new BuildPlayerOptions
{
    locationPathName = "./AndroidExport",
    options = BuildOptions.AcceptExternalModificationsToPlayer,
    target = BuildTarget.Android
};
BuildPipeline.BuildPlayer(options); // fails if ./AndroidExport is stale or missing

// after
string exportDir = "./AndroidExport";
if (!Directory.Exists(Path.Combine(exportDir, "build.gradle")))
{
    if (Directory.Exists(exportDir))
        Directory.Delete(exportDir, recursive: true);
}

var options = new BuildPlayerOptions
{
    locationPathName = exportDir,
    options = BuildOptions.AcceptExternalModificationsToPlayer,
    target = BuildTarget.Android
};
BuildPipeline.BuildPlayer(options);
Defensive patterns

Strategy: validation

Validate before calling

bool IsAppendSafe(string exportDir, BuildTarget target)
{
    if (target != BuildTarget.Android && target != BuildTarget.iOS)
        return false;
    // Android: check for gradle project marker; iOS: check for .xcodeproj or Unity-iPhone.xcodeproj
    return Directory.Exists(exportDir) &&
        Directory.GetFiles(exportDir, "build.gradle", SearchOption.TopDirectoryOnly).Length > 0;
}

// Before BuildPlayer with AcceptExternalModificationsToPlayer:
if (!IsAppendSafe(options.locationPathName, options.target))
{
    if (Directory.Exists(options.locationPathName))
        Directory.Delete(options.locationPathName, recursive: true);
}

Prevention

When it happens

Trigger: Calling BuildPipeline.BuildPlayer with AcceptExternalModificationsToPlayer on Android/iOS when the locationPathName directory either doesn't exist yet, was built by an incompatible Unity version, or has been modified/corrupted since the last export.

Common situations: First incremental export to a directory that was deleted, CI builds on clean agents where the export folder is ephemeral, upgrading Unity major versions and trying to append to an old export, or manually editing the exported project between builds.

Related errors


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