If your Unreal Engine 5.7 CI lane fails with AutomationTool exiting with ExitCode=6, the failing command is usually not the real root cause. Most teams hit this when SDK discovery differs between local and CI machines, or when BuildGraph paths resolve differently on self-hosted runners versus local workstations.
This guide gives you a deterministic fix sequence so your CI job fails fast with actionable checks instead of late-stage packaging crashes.
Problem summary
Common symptoms:
- pipeline logs show
AutomationTool exiting with ExitCode=6 - UAT output references missing SDKs, unresolved scripts, or invalid path arguments
- local package works, but CI package fails on the same commit
- failures appear after runner-image updates, engine patch updates, or path refactors
Impact:
- release branch promotion stalls
- artifact cadence becomes unpredictable near content lock
Root causes
-
SDK detection drift between environments CI machines may have different Visual Studio workloads, Windows SDK versions, Android NDK paths, or environment variables than local build boxes.
-
BuildGraph script or argument path mismatch Relative paths and mixed separators can resolve differently in CI working directories.
-
Engine association and toolchain ambiguity UAT may pick a different engine install or incomplete toolchain if explicit paths are missing.
-
Late failure due to missing preflight checks CI reaches UAT packaging before discovering prerequisites are absent or misconfigured.
Fix steps
Step 1 - Capture the first actionable UAT error, not only ExitCode 6
- store full AutomationTool log as a CI artifact
- search the first failure block before the final
ExitCode=6line - classify the first actionable error into one lane: SDK discovery, BuildGraph path, or engine association
Treat ExitCode=6 as a wrapper status. The first upstream exception is the real fix target.
Step 2 - Pin engine and UAT invocation paths explicitly
- call
RunUAT.batusing absolute paths - avoid relying on current working directory assumptions
- keep one canonical engine path source per runner profile
Example pattern:
- resolve
%UE_ROOT%from CI variables - execute
%UE_ROOT%\Engine\Build\BatchFiles\RunUAT.bat - pass absolute project and script paths
This removes ambiguity after runner-image or checkout-folder changes.
Step 3 - Normalize BuildGraph script and argument paths
- convert all BuildGraph script references to normalized absolute paths
- avoid mixed slash styles in assembled command strings
- ensure quoted paths are used for spaces in workspace or engine directories
If your graph consumes external XML includes or output roots, validate those paths before invoking UAT.
Step 4 - Add deterministic SDK/toolchain preflight checks
Before packaging, run a preflight CI step that verifies:
- expected Visual Studio toolchain and Windows SDK are installed
- required platform SDKs are discoverable in environment variables
- Unreal prerequisites resolve from the same engine root used by UAT
- runner account has read/write access to intermediate and output folders
Failing early here is faster than debugging deep UAT traces.
Step 5 - Validate with a minimal BuildGraph target, then full package
- execute a lightweight graph target to verify path and SDK resolution
- confirm intermediate artifacts are generated in expected directories
- run full packaging only after the minimal target is stable for consecutive runs
This isolates environment issues from content-driven packaging defects.
Verification checklist
- [ ] CI archives full UAT logs and first-failure context for each failed run.
- [ ]
RunUAT.batand project/script inputs use absolute, quoted paths. - [ ] BuildGraph script includes and output directories resolve consistently on runner.
- [ ] Preflight checks validate SDK/toolchain prerequisites before packaging.
- [ ] Minimal BuildGraph target passes repeatedly before full package execution.
Alternative fixes
- If failures started after a runner image refresh, roll back once to compare toolchain diff and then apply a controlled image update.
- If only one branch fails, compare branch-specific CI variables and workspace path transforms against the passing branch.
- If engine patch updates triggered failures, re-validate engine association variables and regenerate project files in the CI bootstrap stage.
Prevention tips
- Version-control a CI preflight script that checks SDK and path prerequisites before UAT.
- Keep BuildGraph entry points centralized so path logic is not duplicated across jobs.
- Lock runner images for release windows and promote updates through a staging CI lane first.
FAQ
Why does ExitCode 6 show up without a clear reason
It usually means AutomationTool wrapped an earlier failure. Parse and surface the first actionable exception in your CI summary so triage starts at the real source.
Why does local packaging pass while CI fails
Local and CI environments often differ in SDK installs, engine paths, permissions, or workspace layout. Deterministic preflight checks eliminate this drift.
Should we skip BuildGraph and package directly
BuildGraph is still useful for repeatable release orchestration. The reliable fix is path normalization plus preflight validation, not removing orchestration.
Related links
- Unreal Engine 5.7 Lumen Flicker in Cinematic Shots - Exposure Lock and Reflection Method Fix
- Unreal Engine Movie Render Queue Output Too Dark or Black - Exposure Tone Mapper and Deferred Capture Fix
- Unity Cloud Diagnostics Symbol Upload Failed - dSYM and ProGuard Mapping Pipeline Fix
- Official docs: AutomationTool Overview and BuildGraph
Bookmark this fix so your Unreal CI lane can catch environment drift early and keep packaging predictable.