Volver al Blog

Cómo solucionar el error de UBA Executor en UBT al compilar Unreal Engine 5.8 desde source

Publicado el 27 de junio de 2026
Cómo solucionar el error de UBA Executor en UBT al compilar Unreal Engine 5.8 desde source

En resumen

Esta guía explica cómo solucionar el error de UBA Executor en Unreal Build Tool (UBT) al compilar Unreal Engine 5.8 desde source. Analiza las causas del crash debido a llamadas recursivas no soportadas por la arquitectura actual de Unreal Build Accelerator. Ofrece tres soluciones prácticas: mediante la modificación de BuildConfiguration.xml, aplicando un parche directo al código de C# de ExecutorFactory.cs, o utilizando flags en la línea de comandos.

Pocas cosas frenan tanto el ritmo de un estudio como una build del motor rota, especialmente al compilar Unreal Engine 5.8.0 desde source y cuando Visual Studio se detiene con una excepción críptica. La build falla con una excepción no controlada que apunta directamente a UBAExecutor.cs. Este bloqueo específico, conocido como el unreal engine uba executor ubt error, detiene por completo la compilación. Evita que el build graph complete la generación de programas auxiliares críticos como UnrealHeaderTool. En esta guía, analizaremos por qué Unreal Build Accelerator (UBA) tiene problemas con las llamadas anidadas, cómo falla la configuración por defecto y cómo aplicar un parche al source de tu motor para restaurar un pipeline de build funcional.

Understanding the Build System Architecture

Para entender por qué ocurre este error, debemos examinar cómo Unreal Build Tool (UBT) organiza la compilación. Las bases de código de Unreal Engine son masivas, y a menudo contienen decenas de miles de archivos de código fuente. Para compilarlas de manera eficiente, UBT actúa como un sistema de meta-build, generando grafos de dependencias y enviando acciones de compilación.

What is Unreal Build Accelerator?

Epic Games introdujo Unreal Build Accelerator (UBA) como el ejecutor de compilación por defecto para reemplazar los sistemas de distribución más antiguos. UBA está diseñado para acelerar la compilación mediante el uso de un sistema de archivos virtualizado (VFS) ligero para interceptar las operaciones de I/O de archivos. Dirige las tareas del compilador a través de múltiples núcleos locales o las distribuye en nodos de build de Horde.

En una máquina de build estándar de 64 núcleos, UBA puede reducir los tiempos de compilación limpia del motor de ~90 minutos a menos de ~25 minutos. Sin embargo, debido a que UBA depende de un agente local centralizado para interceptar la I/O, requiere un control estricto sobre cómo se generan los procesos del compilador.

The Mechanism of Recursive UBT Calls

Durante una ejecución de compilación, UBT a menudo encuentra targets que deben compilarse antes de que los binarios principales del motor puedan hacerlo. Por ejemplo, antes de compilar el ejecutable UnrealEditor, UBT debe compilar UnrealHeaderTool (UHT) para procesar archivos de cabecera y generar metadatos de reflexión.

Para lograr esto, el proceso primario de UBT genera un proceso de UBT secundario y anidado para construir el target prerrequisito. Esta invocación anidada se denomina llamada recursiva de UBT. Cuando una llamada recursiva de UBT está activa, UBT establece un flag interno (UnrealBuildTool.IsRecursive = true) y propaga variables de entorno para marcar el proceso como anidado.

Why the UBA Executor Crashes on Recursive Invocations

El crash ocurre porque el ejecutor de UBA no está diseñado para soportar bucles de compilación anidados. Veamos el call stack típico que lanza UBT cuando ocurre este fallo en Visual Studio:

Unhandled exception: Exception: UBA executor is not expected to be invoked from a recursive UBT call.
   at UnrealBuildTool.UBAExecutor.Init(IEnumerable`1 targetDescriptors, ILogger logger) in UnrealEngine\Engine\Source\Programs\UnrealBuildTool\Executors\UnrealBuildAccelerator\UBAExecutor.cs:line 315
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at UnrealBuildTool.UBAExecutor.ExecuteActionsAsync(IEnumerable`1 inputActions, ILogger logger) in UnrealEngine\Engine\Source\Programs\UnrealBuildTool\Executors\UnrealBuildAccelerator\UBAExecutor.cs:line 617
   at UnrealBuildTool.ActionGraph.InternalExecuteActions(ActionExecutor Executor, List`1 ActionsToExecute, ILogger Logger) in UnrealEngine\Engine\Source\Programs\UnrealBuildTool\Actions\ActionGraph.cs:line 435

The Safety Check in UBAExecutor.cs

Dentro del método UBAExecutor.Init (alrededor de la línea 315 de UBAExecutor.cs), el motor aplica explícitamente una comprobación de seguridad de recursividad:

// Engine/Source/Programs/UnrealBuildTool/Executors/UnrealBuildAccelerator/UBAExecutor.cs
public void Init(IEnumerable<TargetDescriptor> TargetDescriptors, ILogger Logger)
{
    if (UnrealBuildTool.IsRecursive)
    {
        throw new Exception("UBA executor is not expected to be invoked from a recursive UBT call.");
    }
    
    // Virtualized file system and network initialization follow...
}

Esta comprobación de seguridad existe por una razón crucial. El agente local de UBA se vincula a puertos TCP específicos para comunicarse con los procesos auxiliares virtualizados del compilador.

Si una invocación recursiva de UBT intentara inicializar una segunda instancia del ejecutor de UBA, ambas instancias intentarían vincularse a los mismos sockets de red y entrarían en conflicto por los hooks del sistema de archivos virtualizado. Esto provocaría errores de asignación de sockets, corrupción del sistema de archivos o deadlocks indefinidos en la build. La excepción actúa como una barrera protectora.

The Root Cause: Executor selection Failure

El verdadero bug en las builds desde source de Unreal Engine 5.8.0 no es esta comprobación de seguridad. Más bien, es el fallo de la lógica en la factoría de ejecutores al no manejar correctamente las llamadas recursivas.

Cuando UBT determina qué ejecutor utilizar, consulta la clase ExecutorFactory.cs. La factoría comprueba si UBA está habilitado y disponible en la máquina host.

Sin embargo, no verifica si el proceso actual de UBT es una ejecución recursiva. Como resultado, cuando el proceso secundario de UBT se inicia para compilar UnrealHeaderTool, la factoría intenta asignar el UBAExecutor a la build anidada, provocando el crash en el método Init.

The XML Configuration Trap

Muchos desarrolladores intentan sortear este problema modificando el archivo global BuildConfiguration.xml. El consejo habitual en posts de foros antiguos es apagar UBA desactivando la siguiente etiqueta:

<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
    <BuildConfiguration>
        <bAllowUBA>false</bAllowUBA>
    </BuildConfiguration>
</Configuration>

Why bAllowUBA Is Ignored in UE 5.8

Si aplicas la configuración XML anterior a una build desde source de Unreal Engine 5.8.0, el compilador seguirá intentando iniciar UBA y lanzará la excepción. Esto se debe a que el sistema de configuración de build del motor ha sido refactorizado.

La antigua propiedad bAllowUBA está obsoleta y ya no está mapeada a la lógica de selección del ejecutor. En su lugar, el comportamiento de UBA se controla mediante dos propiedades distintas: bAllowUBAExecutor and bAllowUBALocalExecutor.

Dado que UBT no encuentra bAllowUBAExecutor en tu XML, toma el valor por defecto true. Esto anula silenciosamente tu intento de desactivar UBA.

Correct XML Structure for UBA Configuration

Para desactivar con éxito UBA a través de los archivos de configuración, debes utilizar los nombres actualizados de las propiedades XML. A continuación se muestra la estructura correcta para obligar a UBT a recurrir a los ejecutores locales estándar:

<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
    <BuildConfiguration>
        <bAllowUBAExecutor>false</bAllowUBAExecutor>
        <bAllowUBALocalExecutor>false</bAllowUBALocalExecutor>
    </BuildConfiguration>
</Configuration>

Esta configuración omite con éxito UBA. Sin embargo, desactivar UBA por completo significa perder los importantes beneficios de velocidad de compilación que ofrece para tus acciones principales de build.

Step-by-Step Guide to Fixing the Error

Dependiendo de tu flujo de trabajo, puedes elegir resolver este problema a nivel global modificando tu configuración XML, o parcheando directamente el código fuente de UBT para conservar la aceleración de build en las compilaciones no recursivas.

Method 1: The BuildConfiguration.xml Override

Si no deseas modificar el código fuente del motor, puedes desactivar UBA de forma global. Esta es la forma más rápida de lograr que tu proyecto compile, aunque aumentará los tiempos de compilación para builds limpias entre un ~40% y un ~60% según tu hardware.

  1. Localiza o crea tu archivo global BuildConfiguration.xml. En Windows, suele estar ubicado en %AppData%\Roaming\Unreal Engine\UnrealBuildTool\BuildConfiguration.xml. En Linux, se encuentra en ~/.config/Unreal Engine/UnrealBuildTool/BuildConfiguration.xml.
  2. Abre el archivo XML en un editor de texto.
  3. Reemplaza el contenido con el esquema XML actualizado que se muestra a continuación.
  4. Guarda el archivo y reinicia tu build de Visual Studio.
<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
    <BuildConfiguration>
        <bAllowUBAExecutor>false</bAllowUBAExecutor>
        <bAllowUBALocalExecutor>false</bAllowUBALocalExecutor>
    </BuildConfiguration>
</Configuration>

Method 2: Patching UBT Source Code (Recommended)

Dado que estás compilando Unreal Engine 5.8 desde source, la solución recomendada es parchear el código fuente en C# de UBT. Esto permite que UBA se ejecute en tu target de compilación principal mientras fuerza una alternativa al ParallelExecutor estándar durante las llamadas recursivas.

  1. Dirígete al directorio de código fuente de UBT: Engine/Source/Programs/UnrealBuildTool/Executors/.
  2. Abre el archivo ExecutorFactory.cs en Visual Studio o en un editor de texto.
  3. Localiza el método Create. Este método es responsable de evaluar tu configuración y devolver el ActionExecutor adecuado.
  4. Modifica la declaración condicional de selección de UBA para incluir una comprobación de ejecuciones recursivas de UBT.
// Engine/Source/Programs/UnrealBuildTool/Executors/ExecutorFactory.cs

public static ActionExecutor Create(BuildConfiguration BuildConfiguration, List<TargetDescriptor> TargetDescriptors, ILogger Logger)
{
    // Check if UBA is allowed, available, and NOT running recursively
-   if (BuildConfiguration.bAllowUBAExecutor && UBAExecutor.IsAvailable())
+   if (BuildConfiguration.bAllowUBAExecutor && UBAExecutor.IsAvailable() && !UnrealBuildTool.IsRecursive)
    {
        return new UBAExecutor(BuildConfiguration, Logger);
    }

    // Fall back to IncrediBuild if configured
    if (BuildConfiguration.bAllowXGE)
    {
        return new XGEExecutor(BuildConfiguration, Logger);
    }

    // Fall back to standard ParallelExecutor
    return new ParallelExecutor(BuildConfiguration, Logger);
}

Este parche evita que la instancia anidada de UBT seleccione el ejecutor de UBA. En su lugar, la build recursiva (como la compilación de UnrealHeaderTool) se ejecutará de forma segura utilizando el ParallelExecutor local, mientras que la compilación principal del motor continuará utilizando toda la potencia de UBA.

Method 3: Command Line Flags

Si ejecutas tu proceso de build a través de scripts de línea de comandos personalizados o pipelines de CI/CD, puedes desactivar UBA por invocación. Esto es especialmente útil si deseas mantener UBA habilitado para los desarrolladores locales pero desactivarlo en servidores de build remotos.

Para hacer esto, añade el flag -NoUBA a tu comando de build de UBT:

# Example command to build the editor without UBA
Engine\Build\BatchFiles\Build.bat UnrealEditor Win64 Development -NoUBA

Alternativamente, puedes forzar a UBT a usar el ejecutor paralelo estándar especificándolo explícitamente con el flag -Executor:

Engine\Build\BatchFiles\Build.bat UnrealEditor Win64 Development -Executor=Parallel

Cleaning and Regenerating the Build Environment

Después de aplicar cualquiera de las soluciones anteriores, UBT podría fallar al compilar debido a archivos de ensamblado en caché o metadatos intermedios obsoletos. Para asegurarte de que la solución se aplique limpiamente, debes borrar los binarios generados de la herramienta de compilación y regenerar los archivos de proyecto.

For Windows Environments

Ejecuta los siguientes comandos en un símbolo del sistema o en una instancia de PowerShell que apunte al directorio de código fuente de tu Unreal Engine:

:: Delete the cached UBT assembly and build binaries
rd /s /q Engine\Intermediate\Build\UnrealBuildTool
rd /s /q Engine\Binaries\DotNET\UnrealBuildTool

:: Regenerate the project files
GenerateProjectFiles.bat

For Linux and macOS Environments

Ejecuta estos comandos en tu terminal:

# Remove cached build tool data
rm -rf Engine/Intermediate/Build/UnrealBuildTool
rm -rf Engine/Binaries/DotNET/UnrealBuildTool

# Regenerate project files
./GenerateProjectFiles.sh

Una vez que el entorno esté limpio, abre el archivo de solución generado (UE5.sln) en Visual Studio y vuelve a compilar el target. La build ahora debería superar la fase de compilación recursiva sin lanzar la excepción del ejecutor.

Actionable Best Practices for Unreal Engine Source Builds

Compilar un fork personalizado del motor desde el código fuente introduce diversos desafíos de compilación, optimización y empaquetado. Aplicar las siguientes buenas prácticas te ayudará a mantener un pipeline de desarrollo estable y altamente optimizado.

1. Optimize Concurrency to Prevent Memory Starvation

Los compiladores de C++ modernos requieren una cantidad de RAM significativa por hilo de compilación. Al compilar módulos grandes del motor, UBT puede generar más tareas paralelas de las que la RAM de tu sistema puede soportar, lo que provoca page-file thrashing (intercambio excesivo en el archivo de paginación) o crashes del compilador.

Puedes limitar la cantidad máxima de procesadores configurando los ajustes de ParallelExecutor en tu archivo BuildConfiguration.xml:

<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
    <ParallelExecutor>
        <MaxProcessorCount>16</MaxProcessorCount>
        <ProcessorCountMultiplier>1.0</ProcessorCountMultiplier>
    </ParallelExecutor>
</Configuration>

Limita el número a aproximadamente 2 GB of RAM por hilo. Por ejemplo, una máquina con 32 GB de RAM debería limitar el MaxProcessorCount a 16.

2. Master Dedicated Server Asset Stripping

Al desplegar tu juego en la nube, debes evitar compilar assets innecesarios del cliente (como texturas de interfaz de usuario, audio y mallas) en el binario de tu Dedicated Server. Esto reduce los tiempos de inicio del servidor y el uso de memoria, lo cual es crítico para escalar flotas de manera eficiente.

Para aprender a configurar tus scripts de build para excluir estos assets, sigue nuestra guía detallada sobre Unreal Engine Dedicated Server Asset Stripping.

3. Verify Blueprint and Package Integrity Early

Una build exitosa del motor no garantiza que tu proyecto se empaquete sin errores. Los blueprints obsoletos o los errores de serialización a menudo causan crashes durante la fase final de empaquetado.

Para evitar que estos problemas bloqueen tu pipeline de lanzamiento, lee nuestra guía sobre Resolving the Unreal Package HasValidBlueprint Ensure Crash para configurar comprobaciones de validación automatizadas.

4. Configure UBA VFS Caching Correctly

Si decides mantener UBA habilitado usando el parche de C#, configura la caché de sistema de archivos virtual para almacenar los archivos objeto compilados localmente. Esto te permite evitar la recompilación de archivos fuente sin modificar al cambiar de rama.

Añade el bloque de configuración UnrealBuildAccelerator a tu archivo XML para habilitar el almacenamiento en caché:

<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
    <UnrealBuildAccelerator>
        <WriteCache>true</WriteCache>
        <Cache>127.0.0.1</Cache>
    </UnrealBuildAccelerator>
</Configuration>

Asegúrate de que tu firewall no bloquee los puertos de comunicación de red local de UBA, que se utilizan para gestionar el bucle de sincronización de la caché.

Elevating Your Backend Architecture

Resolver problemas de build como el unreal engine uba executor ubt error es crucial para mantener un flujo de trabajo de desarrollo saludable. Sin embargo, configurar un entorno de compilación local es solo el primer paso para crear un juego Multiplayer moderno.

Once your custom engine is compiled and your dedicated servers are ready, you must address the complex challenges of backend infrastructure. Writing your own server orchestration, matchmaking algorithms, and persistence databases from scratch requires weeks of development time.

Configurar Load Balancers, sharding de bases de datos y la gestión de certificados SSL puede llevar fácilmente de 4 a 6 semanas de trabajo dedicado. Con horizOn, estos servicios de Backend vienen preconfigurados y listos para escalar.

En lugar de escribir código de infraestructura, puedes integrar datos de jugadores, lobbies en tiempo real y escalado de servidores con unas pocas llamadas simples a la API. Esto te permite desplegar builds de Dedicated Server y gestionar el estado del jugador sin costes adicionales de mantenimiento. Tu equipo puede enfocarse en las mecánicas de juego y las características del motor mientras horizOn se encarga de la infraestructura en la nube.

Next Steps

Para resolver este error de build, elige la opción rápida de omitir mediante XML o aplica el parche del código fuente en C# en ExecutorFactory.cs. Una vez que tu pipeline de build funcione sin problemas, busca formas de optimizar tu flujo de trabajo de despliegue. Si deseas escalar tu juego Multiplayer sin la complicación de alojar servidores personalizados, prueba horizOn gratis o consulta nuestra documentación de la API para obtener más información.


Source: Unhandled exception: Exception: UBA executor is not expected to be invoked from a recursive UBT call.