title: Flattening of AggregateExceptions for Processing
body: <p>I'm running into a few issues where I call <code>flatten</code> on an <code>AggregateException</code>, but inside there is still ANOTHER <code>AggregateException</code>!  This obviously means that they are being propagated up the chain and being rolled into another <code>AggregateException</code>.  Is there a way to recursively flatten ALL inner AggregateExceptions?  Usually, I'll use the handle delegate to process these, but it returns false if there is another inner AggregateExceeption.  Am I not handling these properly?</p>
  
  <p>EDIT:  Since I already am calling Flatten, it appears that the issue is that it's not being caught until way later in the callstack.  Here is the code where I'm calling Flatten().  For use in the stack trace this method is called WriteExceptionRecord(string, FileInfo):</p>
  
  <pre><code>do
  {
      try
      {
          using (var stream = file.Open(FileMode.Append, FileAccess.Write, FileShare.None))
          {
              using (StreamWriter writer = new StreamWriter(stream))
              {
                  await writer.WriteLineAsync(data);
              }
          }
      }
      catch (AggregateException ex)
      {
          ex.Flatten().Handle((x) =&gt;
          {
              if (x is IOException)
              {
                  retryNeeded = true;
                  retryLeft--;
                  Thread.Sleep(500);
                  return true;
              }
  
              logger.ErrorException("Could not write to exception file: " + data, ex);
              return false;
          });
      }
  }
  while (retryNeeded &amp;&amp; retryLeft &gt; 0);
  </code></pre>
  
  <p>However, the stack trace shows that it's not being caught here.  Instead it's being caught way later up the call stack.  Below is the trace with some identifying information removed for security reasons:</p>
  
  <pre><code>System.AggregateException: One or more errors occurred. ---&gt;      
  System.AggregateException: One or more errors occurred. ---&gt;
  System.IO.IOException: The process cannot access the file 'X:\Production\ProductionBatches\DataEntry\J\PD\Exception.csv' because it is being used by another process.    
     at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)    
     at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)    
     at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)    
     at System.IO.FileInfo.Open(FileMode mode, FileAccess access, FileShare share)    
     at PDI.LoadFileProcessing.&lt;WriteExceptionRecord&gt;d__21.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 328
  
  --- End of stack trace from previous location where exception was thrown ---  
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
     at PDI.LoadFileProcessing.&lt;ExceptionRecordProcessing&gt;d__17.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 316
  
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
     at PDI.ProcessPipeline.&lt;&gt;c__DisplayClass9.&lt;&lt;ProcessBatch&gt;b__2&gt;d__13.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\ProcessPipeline.cs:line 61
  
     --- End of inner exception stack trace ---
  
     --- End of inner exception stack trace ---
  
  ---&gt; (Inner Exception #0) System.AggregateException: One or more errors occurred. ---&gt; System.IO.IOException: The process cannot access the file 'X:\Production\ProductionBatches\DataEntry\J\PD\Exception.csv' because it is being used by another process.
     at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
     at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
     at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
     at System.IO.FileInfo.Open(FileMode mode, FileAccess access, FileShare share)
     at PeopleDocImporter.LoadFileProcessing.&lt;WriteExceptionRecord&gt;d__21.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 328
  
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
     at PDI.LoadFileProcessing.&lt;ExceptionRecordProcessing&gt;d__17.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 316
  
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
     at PDI.ProcessPipeline.&lt;&gt;c__DisplayClass9.&lt;&lt;ProcessBatch&gt;b__2&gt;d__13.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\ProcessPipeline.cs:line 61
  
     --- End of inner exception stack trace ---
  ---&gt; (Inner Exception #0) System.IO.IOException: The process cannot access the file 'X:\Production\ProductionBatches\DataEntry\J\PD\Exception.csv' because it is being used by another process.
     at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
     at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
     at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
     at System.IO.FileInfo.Open(FileMode mode, FileAccess access, FileShare share)
     at PDI.LoadFileProcessing.&lt;WriteExceptionRecord&gt;d__21.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 328
  
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
     at PDI.LoadFileProcessing.&lt;ExceptionRecordProcessing&gt;d__17.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 316
  
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)    
     at System.Runtime.CompilerServices.TaskAwaiter.GetResult()    
     at PDI.ProcessPipeline.&lt;&gt;c__DisplayClass9.&lt;&lt;ProcessBatch&gt;b__2&gt;d__13.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\ProcessPipeline.cs:line 61&lt;---
  
  &lt;---
  
  System.AggregateException: One or more errors occurred. ---&gt; System.AggregateException: One or more errors occurred. ---&gt; System.IO.IOException: The process cannot access the file 'X:\Production\ProductionBatches\DataEntry\J\PD\Exception.csv' because it is being used by another process.    
     at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)    
     at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)    
     at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)    
     at System.IO.FileInfo.Open(FileMode mode, FileAccess access, FileShare share)    
     at PDI.LoadFileProcessing.&lt;WriteExceptionRecord&gt;d__21.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 328
  
  --- End of stack trace from previous location where exception was thrown ---    
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)    
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)    
     at System.Runtime.CompilerServices.TaskAwaiter.GetResult()    
     at PDI.LoadFileProcessing.&lt;ExceptionRecordProcessing&gt;d__17.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 316
  
  --- End of stack trace from previous location where exception was thrown ---    
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)    
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)    
     at System.Runtime.CompilerServices.TaskAwaiter.GetResult()    
     at PDI.ProcessPipeline.&lt;&gt;c__DisplayClass9.&lt;&lt;ProcessBatch&gt;b__2&gt;d__13.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\ProcessPipeline.cs:line 61
  
     --- End of inner exception stack trace ---
  
  ---&gt; (Inner Exception #0) System.AggregateException: One or more errors occurred. ---&gt; System.IO.IOException: The process cannot access the file 'X:\J\PD\Exception.csv' because it is being used by another process.    
     at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)    
     at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)    
     at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)    
     at System.IO.FileInfo.Open(FileMode mode, FileAccess access, FileShare share)    
     at PDI.LoadFileProcessing.&lt;WriteExceptionRecord&gt;d__21.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 328
  
  --- End of stack trace from previous location where exception was thrown ---    
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)    
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)    
     at System.Runtime.CompilerServices.TaskAwaiter.GetResult()    
     at PDI.LoadFileProcessing.&lt;ExceptionRecordProcessing&gt;d__17.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 316
  
  --- End of stack trace from previous location where exception was thrown ---    
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)    
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)    
     at System.Runtime.CompilerServices.TaskAwaiter.GetResult()    
     at PDI.ProcessPipeline.&lt;&gt;c__DisplayClass9.&lt;&lt;ProcessBatch&gt;b__2&gt;d__13.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\ProcessPipeline.cs:line 61
  
     --- End of inner exception stack trace ---    
  ---&gt; (Inner Exception #0) System.IO.IOException: The process cannot access the file 'X:\Production\ProductionBatches\DataEntry\J\PD\Exception.csv' because it is being used by another process.    
     at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)    
     at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)    
     at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)    
     at System.IO.FileInfo.Open(FileMode mode, FileAccess access, FileShare share)    
     at PDI.LoadFileProcessing.&lt;WriteExceptionRecord&gt;d__21.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 328
  
  --- End of stack trace from previous location where exception was thrown ---    
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)    
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)    
     at System.Runtime.CompilerServices.TaskAwaiter.GetResult()    
     at PDI.LoadFileProcessing.&lt;ExceptionRecordProcessing&gt;d__17.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\LoadFileProcessing.cs:line 316
  
  --- End of stack trace from previous location where exception was thrown ---    
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)    
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)    
     at System.Runtime.CompilerServices.TaskAwaiter.GetResult()    
     at PDI.ProcessPipeline.&lt;&gt;c__DisplayClass9.&lt;&lt;ProcessBatch&gt;b__2&gt;d__13.MoveNext() in c:\Users\XYZ\Development\PDI\PDI\ProcessPipeline.cs:line 61&lt;---
  </code></pre>
  
  <p>By the way:  This is being called by TPL-Dataflow blocks.</p>