Unity-Technologies/UnityCsReference · error · Exception

{nameof(UnitySourceFileUpdatersResultHandler)} can only be c

Error message

{nameof(UnitySourceFileUpdatersResultHandler)} can only be created on the main thread

What it means

Thrown from the UnitySourceFileUpdatersResultHandler constructor: it must be created on the main thread because it captures the synchronization context and interacts with consent UI. Creating it on a worker thread is rejected via InternalEditorUtility.CurrentThreadIsMainThread().

Source

Thrown at Editor/Mono/Scripting/ScriptCompilation/BeeDriver/UnitySourceFileUpdatersResultHandler.cs:32

using UnityEditorInternal.APIUpdating;
using UnityEngine;
using System.Threading.Tasks;
using UnityEditorInternal;

namespace UnityEditor.Scripting.ScriptCompilation
{
    class UnitySourceFileUpdatersResultHandler : SourceFileUpdatersResultHandler
    {
        bool m_HaveConsentToOverwriteUserScripts;

        readonly UnityScriptUpdaterConsentAPI ConstentAPI;

        public UnitySourceFileUpdatersResultHandler() : base(captureSynchronizationContext: true)
        {
            ConstentAPI = new UnityScriptUpdaterConsentAPI();

            if (!InternalEditorUtility.CurrentThreadIsMainThread())
                throw new Exception($"{nameof(UnitySourceFileUpdatersResultHandler)} can only be created on the main thread");
        }


        protected override bool ProcessUpdaterResults(SourceFileUpdaterBase.Update[] updates)
        {
            var problemUpdates = new List<(SourceFileUpdaterBase.Update update, Exception exception)>();
            bool didUpdate = false;
            void ExecuteUpdates(IEnumerable<SourceFileUpdaterBase.Update> updates)
            {
                foreach (var update in updates)
                {
                    didUpdate = true;
                    try
                    {
                        Console.WriteLine(update.originalFileWithError);
                        new NPath(update.tempFileWithNewContents).Copy(update.originalFileWithError);
                    }
                    catch (Exception e)

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Construct the handler on the main thread (e.g. queue the creation to the main thread / EditorApplication update).
  2. Marshal background continuations back to the main thread before creating main-thread-only objects.

Example fix

// before
Task.Run(() => { var h = new UnitySourceFileUpdatersResultHandler(); ... });
// after
EditorApplication.delayCall += () => { var h = new UnitySourceFileUpdatersResultHandler(); ... };
Defensive patterns

Strategy: validation

Validate before calling

if (!InternalEditorUtility.CurrentThreadIsMainThread())
    throw new InvalidOperationException("Construct this handler on the main thread.");

Type guard

static bool IsMainThread() => InternalEditorUtility.CurrentThreadIsMainThread();

Try / catch

try { var h = new UnitySourceFileUpdatersResultHandler(); }
catch (Exception ex) when (ex.Message.Contains("main thread"))
{ /* re-run the construction via EditorApplication.delayCall / main thread dispatch */ }

Prevention

When it happens

Trigger: Instantiating UnitySourceFileUpdatersResultHandler on a non-main thread (e.g. inside a Task or thread pool callback).

Common situations: Driving the script updater from a background task/thread, or constructing the handler inside an async continuation that did not marshal back to the main thread.

Related errors


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