<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Laurent Gouhier</title>
    <description>The latest articles on DEV Community by Laurent Gouhier (@elrendir).</description>
    <link>https://dev.to/elrendir</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4220926%2Fd34e4b93-ceef-42c4-ab49-bfcd1cd67f87.jpg</url>
      <title>DEV Community: Laurent Gouhier</title>
      <link>https://dev.to/elrendir</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/elrendir"/>
    <language>en</language>
    <item>
      <title>The last error in an Unreal Engine cook log is often a lie: notes from 37 controlled runs</title>
      <dc:creator>Laurent Gouhier</dc:creator>
      <pubDate>Sun, 01 Nov 2026 16:58:43 +0000</pubDate>
      <link>https://dev.to/elrendir/the-last-error-in-an-unreal-engine-cook-log-is-often-a-lie-notes-from-37-controlled-runs-268a</link>
      <guid>https://dev.to/elrendir/the-last-error-in-an-unreal-engine-cook-log-is-often-a-lie-notes-from-37-controlled-runs-268a</guid>
      <description>&lt;p&gt;If you've packaged an Unreal Engine project, you've probably seen this at the bottom of a log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AutomationTool exiting with ExitCode=25 (Error_UnknownCookFailure)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, in the editor, &lt;code&gt;PackagingResults: Error: Unknown Cook Failure&lt;/code&gt;. Search for it and you'll find years of forum threads where someone pastes those last lines, someone else asks for the full log, and the thread dies.&lt;/p&gt;

&lt;p&gt;I wanted to know what these logs actually look like when you &lt;em&gt;know&lt;/em&gt; the cause. So I built a small test project and broke it on purpose, in a controlled and repeatable way, on Unreal Engine 5.4.4 and 5.8.3.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;13 clean baseline runs&lt;/strong&gt; (command line and editor) that package successfully.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;24 sabotaged runs&lt;/strong&gt; across six scenarios, each run twice on both engine versions:

&lt;ul&gt;
&lt;li&gt;a project plugin that crashes in &lt;code&gt;StartupModule()&lt;/code&gt; during the cook,&lt;/li&gt;
&lt;li&gt;the same plugin copied twice under &lt;code&gt;Plugins/&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;.Build.cs&lt;/code&gt; whose class name doesn't match the module,&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;.uplugin&lt;/code&gt; that declares a module with no rules file,&lt;/li&gt;
&lt;li&gt;deleted assets still referenced by a soft or a hard reference.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All logs are scrubbed of user, machine and path information. To be clear about the limits: this is one project on one machine, and every failure is synthetic. It shows &lt;em&gt;how&lt;/em&gt; Unreal reports these failures, not how often they happen in the wild.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 1: the exit code is a stage, not a cause
&lt;/h2&gt;

&lt;p&gt;Three codes carry most of the meaning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ExitCode=8&lt;/code&gt;: UnrealBuildTool failed. The cook never started.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ExitCode=25 (Error_UnknownCookFailure)&lt;/code&gt;: the cook failed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ExitCode=3&lt;/code&gt; (on the &lt;code&gt;Took ...s to run UnrealEditor-Cmd.exe&lt;/code&gt; line): the return code of the cook process itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of my 16 failed runs, 12 ended with &lt;code&gt;ExitCode=8&lt;/code&gt;. That ratio comes from the scenarios I chose, but it's a useful reminder: before you dig through cook output, check whether there was a cook at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 2: the real crash is above a wall of C# stack trace
&lt;/h2&gt;

&lt;p&gt;Here's the plugin crash, from the &lt;code&gt;Cook-*.txt&lt;/code&gt; log (5.4.4, paths anonymized):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LogWindows: Error: begin: stack for UAT
LogWindows: Error: === Critical error: ===
LogWindows: Error:
LogWindows: Error: Fatal error!
LogWindows: Error:
LogWindows: Error: Unhandled Exception: EXCEPTION_ACCESS_VIOLATION writing address 0x0000000000000000
LogWindows: Error:
LogWindows: Error: [Callstack] 0x00007ffa774f1604 UnrealEditor-MyPlugin.dll!FMyPluginModule::StartupModule() [C:\Projects\MyProject\Plugins\MyPlugin\Source\MyPlugin\Private\MyPlugin.cpp:21]
LogWindows: Error: [Callstack] 0x00007ffa04e1e42b UnrealEditor-Core.dll!UnknownFunction []
LogWindows: Error: [Callstack] 0x00007ffa0479a944 UnrealEditor-Projects.dll!UnknownFunction []
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two details matter. First, the first line tagged &lt;code&gt;Error:&lt;/code&gt; is &lt;code&gt;begin: stack for UAT&lt;/code&gt;, a banner and not a cause, so a naive "find the first error" search stops in the wrong place. Second, the useful line is the first non-engine module in the callstack: &lt;code&gt;UnrealEditor-MyPlugin.dll&lt;/code&gt;. That names the plugin to update or disable.&lt;/p&gt;

&lt;p&gt;In the main &lt;code&gt;Log.txt&lt;/code&gt;, the crash is relayed at line 7057 of 7095. The last ~40 lines are an AutomationTool stack trace, &lt;code&gt;Cook failed.&lt;/code&gt;, and the &lt;code&gt;ExitCode=25&lt;/code&gt; line. If you only paste the tail, you paste the part with no information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 3: the line right after the cause looks like a different error
&lt;/h2&gt;

&lt;p&gt;Here's the duplicated plugin (5.8.3, &lt;code&gt;Log.txt&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...\Plugins\Copies\MyPlugin\...\MyPlugin.Build.cs(5,14): error CS0101: The namespace '&amp;lt;global namespace&amp;gt;' already contains a definition for 'MyPlugin'
...\Plugins\Copies\MyPlugin\...\MyPlugin.Build.cs(7,9): error CS0111: Type 'MyPlugin' already defines a member called 'MyPlugin' with the same parameter types
Expecting to find a type to be declared in a target rules named 'MyProjectEditorTarget'.

Result: Failed (RulesError)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's no "duplicate plugin" message anywhere. UnrealBuildTool compiles every &lt;code&gt;.Build.cs&lt;/code&gt; of the project into one C# assembly, so two copies of the same plugin declare the same class twice, and the C# compiler reports &lt;code&gt;CS0101&lt;/code&gt;. The next line, &lt;code&gt;Expecting to find a type to be declared in a target rules named...&lt;/code&gt;, looks like a classic broken-Target.cs error with its own forum threads, but here it's only a consequence.&lt;/p&gt;

&lt;p&gt;The fix is in the first line: its path points to the second copy (&lt;code&gt;Plugins/Copies/...&lt;/code&gt;). Every subfolder of &lt;code&gt;Plugins/&lt;/code&gt; is scanned, including the one where you parked a backup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 4: a successful build can still ship a broken game
&lt;/h2&gt;

&lt;p&gt;8 of the 24 sabotaged runs ended with &lt;code&gt;BUILD SUCCESSFUL&lt;/code&gt; and &lt;code&gt;ExitCode=0&lt;/code&gt;. All of them were assets deleted while still referenced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5.4.4, soft reference: no trace in any log.&lt;/li&gt;
&lt;li&gt;5.4.4, hard reference: a &lt;code&gt;Warning: Failed to load '/Game/...': Can't find file.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;5.8.3, both: the same Display-level line, &lt;code&gt;Package ... has a dependency on package ... which does not exist&lt;/code&gt;. You can't tell soft from hard in the log.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a mesh or sound is missing in your packaged build, search the log for those strings even when packaging "worked".&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 5: my own expectation was wrong once
&lt;/h2&gt;

&lt;p&gt;One scenario was designed to trigger &lt;code&gt;Expecting to find a type to be declared in a module rules named '...'&lt;/code&gt;. On both versions it produced &lt;code&gt;Could not find definition for module '...'&lt;/code&gt; instead: a different error, with a different fix (the module has no &lt;code&gt;.Build.cs&lt;/code&gt; at all). That's now its own rule. Error messages are specific, so match the exact text.&lt;/p&gt;

&lt;h2&gt;
  
  
  And one from the real world
&lt;/h2&gt;

&lt;p&gt;A few days ago someone on Reddit shared a packaging log that started like this (anonymized):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LogTurnkeySupport: Warning: Turnkey failed to run properly, full Turnkey output:
Running AutomationTool...
...
Building 1 projects...
...\Build\Scripts\obj\...\MyProject.Automation.AssemblyInfo.cs(13,12): error CS0579: Duplicate 'System.Reflection.AssemblyCompanyAttribute' attribute
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything about the first line says "your platform SDK is broken". It isn't. Before Turnkey can check any SDK, AutomationTool compiles the project's own automation scripts (&lt;code&gt;Build/Scripts/*.Automation.csproj&lt;/code&gt;), and that compile failed: the assembly attributes were generated twice. The usual suspects are leftover &lt;code&gt;obj&lt;/code&gt;/&lt;code&gt;bin&lt;/code&gt; folders or a project copy that's off in some other way. In this case, deleting &lt;code&gt;obj&lt;/code&gt; didn't help, but re-downloading the project did. So if cleaning the build folders doesn't work, get a fresh copy of the project before touching your SDK.&lt;/p&gt;

&lt;p&gt;Same lesson as Finding 3: the scary line at the top is the messenger, the &lt;code&gt;error CS&lt;/code&gt; line underneath is the message.&lt;/p&gt;

&lt;h2&gt;
  
  
  A checklist that works without any tool
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Check the exit code: 8 means build stage, 25 means cook stage.&lt;/li&gt;
&lt;li&gt;Search from the top for &lt;code&gt;Error:&lt;/code&gt;, &lt;code&gt;error CS&lt;/code&gt;, &lt;code&gt;error C&lt;/code&gt;, &lt;code&gt;Assertion failed&lt;/code&gt;, &lt;code&gt;Unhandled Exception&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Skip banners and summaries: &lt;code&gt;begin: stack for UAT&lt;/code&gt;, &lt;code&gt;Fatal error!&lt;/code&gt;, &lt;code&gt;PackagingResults&lt;/code&gt;, &lt;code&gt;Cook failed&lt;/code&gt;, &lt;code&gt;ExitCode=&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;Log.txt&lt;/code&gt; says &lt;code&gt;UnrealBuildTool failed. See log for more details&lt;/code&gt;, open the &lt;code&gt;UBA-*.txt&lt;/code&gt; it names.&lt;/li&gt;
&lt;li&gt;If Turnkey complains but &lt;code&gt;error CS&lt;/code&gt; lines follow, fix the C# error first: it's a script build problem, not an SDK one.&lt;/li&gt;
&lt;li&gt;Even on success, search for &lt;code&gt;which does not exist&lt;/code&gt; and &lt;code&gt;Can't find file&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Disclosure
&lt;/h2&gt;

&lt;p&gt;I turned these rules into a free, in-browser decoder: &lt;a href="https://cookfail.dev" rel="noopener noreferrer"&gt;cookfail.dev&lt;/a&gt;. It documents 26 error patterns and detects 23 of them automatically. 6 were reproduced in the lab described here, one comes from that real user's log, and the rest come from forum threads and haven't been reproduced yet.&lt;/p&gt;

&lt;p&gt;Your log never leaves your browser. If the decoder gets it wrong, the feedback button lets you tell me the actual cause, and real-world logs are exactly what this test set needs most.&lt;/p&gt;

</description>
      <category>unrealengine</category>
      <category>gamedev</category>
      <category>debugging</category>
    </item>
  </channel>
</rss>
