Unity-Technologies/UnityCsReference · error · NotSupportedException

Deployment targets main thread context can only be…

Error message

Deployment targets main thread context can only be retrieved from the main thread.

What it means

Thrown by DefaultDeploymentTargetsExtension.GetMainThreadContext via CheckGetMainThreadContextCalledOnMainThread when the call is not on the Unity main thread. Deployment target discovery (ADB device enumeration on Android, etc.) is main-thread-affined because it touches native editor state. NotSupportedException signals that the operation has an inviolable precondition, not a recoverable failure.

Solutions

  1. Marshal the call to the main thread: wrap it in EditorApplication.delayCall or a main-thread dispatcher before invoking the deployment API.
  2. Restructure async code to do the DeploymentTargetManager work synchronously on the main thread and only offload non-Unity work to background tasks.
  3. If you control the entry point, assert InternalEditorUtility.CurrentThreadIsMainThread() at the top of the method that leads here.

Example fix

// before
await Task.Run(() => manager.GetKnownTargets());
// after
List<DeploymentTargetIdAndStatus> targets = null;
EditorApplication.delayCall += () => { targets = manager.GetKnownTargets(); };
Defensive patterns

Strategy: validation

Validate before calling

if (!UnityEngine.InternalEditorUtility.CurrentThreadIsMainThread())
    throw new InvalidOperationException("Must be on main thread");
// or marshal:
// EditorApplication.delayCall += () => DoDeploymentWork();

Try / catch

try { ctx = ext.GetMainThreadContext(setup); }
catch (NotSupportedException ex) when (ex.Message.Contains("main thread"))
{ /* re-dispatch to main thread via EditorApplication.delayCall */ }

Prevention

When it happens

Trigger: Calling any DeploymentTargetManager API that internally calls GetMainThreadContext (e.g. constructing DeploymentTargetManager, GetKnownTargets) from a Task, a ThreadPool callback, or a background thread without marshalling back to the main thread.

Common situations: Build pipeline running device deployment steps on a background task; a CI script invoking deployment target enumeration off the main thread; async/await continuation that lost the main thread synchronization context after an await.

Related errors


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

Appendix: source

Thrown at Editor/Mono/DeploymentTargets/DefaultDeploymentTargetsExtension.cs:61

        internal override void Stop() {}

        internal override void Clear() {}
    }

    internal abstract class DefaultDeploymentTargetsExtension
        : IDeploymentTargetsExtension
    {
        public virtual IDeploymentTargetsMainThreadContext GetMainThreadContext(bool setup)
        {
            CheckGetMainThreadContextCalledOnMainThread();
            return new DefaultDeploymentTargetsMainThreadContext();
        }

        protected void CheckGetMainThreadContextCalledOnMainThread()
        {
            if (!InternalEditorUtility.CurrentThreadIsMainThread())
                throw new NotSupportedException("Deployment targets main thread context can only be retrieved from the main thread.");
        }

        public virtual List<DeploymentTargetIdAndStatus> GetKnownTargets(IDeploymentTargetsMainThreadContext context, ProgressHandler progressHandler = null)
        {
            return new List<DeploymentTargetIdAndStatus>();
        }

        public virtual IDeploymentTargetInfo GetTargetInfo(IDeploymentTargetsMainThreadContext context, DeploymentTargetId targetId, ProgressHandler progressHandler = null)
        {
            return new DefaultDeploymentTargetInfo();
        }

        public virtual DeploymentTargetLogger GetTargetLogger(IDeploymentTargetsMainThreadContext context, DeploymentTargetId targetId)
        {
            return new DefaultDeploymentTargetLogger();
        }

        public virtual IDeploymentLaunchResult LaunchBuildOnTarget(IDeploymentTargetsMainThreadContext context, BuildProperties buildProperties, DeploymentTargetId targetId, ProgressHandler progressHandler = null)

View on GitHub (pinned to 225b0fbdb5)