Unity-Technologies/UnityCsReference · critical · System.Exception

Build platforms are not initialized.

Error message

Build platforms are not initialized.

What it means

Thrown by EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget when BuildPlatforms.instance is null for a non-Standalone build target. The build-platforms subsystem must be initialized before this helper can resolve a NamedBuildTarget to a BuildTarget; querying it too early (during editor boot, before the build window registers platforms) throws.

Solutions

  1. Defer the call until after editor initialization (EditorApplication.update callback, deferred once).
  2. Restrict to Standalone targets during early init, or short-circuit when BuildPlatforms.instance is null.
  3. Guard with a null check on BuildPlatforms.instance and skip/log instead of forcing the call.
  4. Move build-target queries out of [InitializeOnLoad] into a delayed initialization path.

Example fix

// before
[InitializeOnLoad]
static class C {
  static C() {
    var t = EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget(namedTarget);
  }
}

// after
[InitializeOnLoad]
static class C {
  static C() {
    EditorApplication.delayCall += () => {
      if (BuildPlatforms.instance != null)
        var t = EditorUserBuildSettingsUtils.CalculateSelectedBuildTarget(namedTarget);
    };
  }
}
Defensive patterns

Strategy: validation

Validate before calling

if (BuildPlatforms.instance == null) { Debug.LogWarning("Build platforms not ready; deferring"); return BuildTarget.NoTarget; }

Type guard

static bool AreBuildPlatformsReady => BuildPlatforms.instance != null;

Prevention

When it happens

Trigger: Calling CalculateSelectedBuildTarget (directly or via build pipeline code) for a non-Standalone NamedBuildTarget during early editor initialization, before BuildPlatforms has been constructed by the build window/editor load sequence.

Common situations: An editor startup script or [InitializeOnLoad] method that queries the selected build target before the build subsystem is ready; headless editor runs where the build window was never opened; package code that calls build settings helpers at static-constructor time.

Related errors


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

Appendix: source

Thrown at Editor/Mono/EditorUserBuildSettingsUtils.cs:29

        public static BuildTarget CalculateSelectedBuildTarget()
        {
            NamedBuildTarget namedBuildTarget = CalculateSelectedNamedBuildTarget();
            return CalculateSelectedBuildTarget(namedBuildTarget);
        }

        internal static BuildTarget CalculateSelectedBuildTarget(NamedBuildTarget namedBuildTarget)
        {
            if (namedBuildTarget.ToBuildTargetGroup() == BuildTargetGroup.Standalone)
            {
                BuildTarget target = EditorUserBuildSettings.selectedStandaloneTarget;
                if (target == BuildTarget.NoTarget)
                    target = EditorUserBuildSettings.activeBuildTarget;
                return DesktopStandaloneBuildWindowExtension.GetBestStandaloneTarget(target);
            }
            else
            {
                if (BuildPlatforms.instance == null)
                    throw new System.Exception("Build platforms are not initialized.");
                BuildPlatform platform = BuildPlatforms.instance.BuildPlatformFromNamedBuildTarget(namedBuildTarget);
                if (platform == null)
                    throw new System.Exception("Could not find build platform for target group " + namedBuildTarget.TargetName);
                return platform.defaultTarget;
            }
        }

        public static NamedBuildTarget CalculateSelectedNamedBuildTarget()
        {
            BuildTargetGroup targetGroup = EditorUserBuildSettings.selectedBuildTargetGroup;
            if (targetGroup == BuildTargetGroup.Unknown)
                targetGroup = EditorUserBuildSettings.activeBuildTargetGroup;

            // TODO: Eventually NamedBuildTarget will replace completetly BuildTargetGroup, and we won't need this custom check
            if (targetGroup == BuildTargetGroup.Standalone)
            {
                if (EditorUserBuildSettings.selectedStandaloneBuildSubtarget == StandaloneBuildSubtarget.Server)
                    return NamedBuildTarget.Server;

View on GitHub (pinned to 225b0fbdb5)