Unity-Technologies/UnityCsReference · error · NotSupportedException
Deployment targets main thread context can only be retrieved
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.
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)
Solutions
- Marshal the call to the main thread: wrap it in EditorApplication.delayCall or a main-thread dispatcher before invoking the deployment API.
- Restructure async code to do the DeploymentTargetManager work synchronously on the main thread and only offload non-Unity work to background tasks.
- 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
- Assume all DeploymentTargetManager APIs are main-thread-affined.
- Do not await between fetching the context and using it.
- Assert main-thread at the entry point of any build/deployment routine.
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
- Platform does not implement DeploymentTargetsExtension
- The build cannot be appended.
- {nameof(UnitySourceFileUpdatersResultHandler)} can only be c
- Value for parameter atlases is null
- One of the elements in atlases is null. Please check your In
AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13).
Data as JSON: /api/errors/4308e6e994992bf3.
Report an issue: GitHub.