title: OpenXml "Can not access a closed stream" only on production
body: <p>Production Environment: Server 2008 R2, Application pool running as network service.
  I'm running into this issue in production on a specific line and I cannot understand why it is failing.</p>
  
  <p>Log with stack trace:</p>
  
  <pre><code>2015-02-03 11:19:29,389,DEBUG,44,Before Test1
  2015-02-03 11:19:29,389,DEBUG,44,Before Test2
  2015-02-03 11:19:29,451,DEBUG,44,Before Getting Row
  2015-02-03 11:19:29,451,DEBUG,44,After Getting Row
  2015-02-03 11:19:29,826,DEBUG,44,Before Test1
  2015-02-03 11:19:29,841,DEBUG,44,Before Test2
  2015-02-03 11:19:29,841,DEBUG,44,Before Getting Row
  2015-02-03 11:19:29,841,DEBUG,44,After Getting Row
  2015-02-03 11:19:30,044,DEBUG,44,Before Test1
  2015-02-03 11:19:30,060,DEBUG,44,Before Test2
  2015-02-03 11:19:30,075,DEBUG,44,Before Getting Row
  2015-02-03 11:19:30,075,DEBUG,44,After Getting Row
  2015-02-03 11:19:30,138,DEBUG,44,Before Test1
  2015-02-03 11:19:30,138,DEBUG,44,Before Test2
  2015-02-03 11:19:30,356,DEBUG,44,Before Getting Row
  2015-02-03 11:19:30,356,DEBUG,44,After Getting Row
  2015-02-03 11:19:31,058,DEBUG,44,Before Test1
  2015-02-03 11:19:31,074,DEBUG,44,Before Test2
  2015-02-03 11:19:31,245,DEBUG,44,Before Getting Row
  2015-02-03 11:19:31,245,DEBUG,44,After Getting Row
  2015-02-03 11:19:31,729,DEBUG,44,Before Test1
  2015-02-03 11:19:31,729,DEBUG,44,Before Test2
  2015-02-03 11:19:31,745,DEBUG,44,Before Getting Row
  2015-02-03 11:19:31,745,DEBUG,44,After Getting Row
  2015-02-03 11:19:31,776,DEBUG,44,Before Test1
  2015-02-03 11:19:31,791,DEBUG,44,Before Test2
  2015-02-03 11:19:31,807,DEBUG,44,Before Getting Row
  2015-02-03 11:19:31,807,DEBUG,44,After Getting Row
  2015-02-03 11:19:31,869,DEBUG,44,Before Test1
  2015-02-03 11:19:31,869,DEBUG,44,Before Test2
  2015-02-03 11:19:31,885,DEBUG,44,Before Getting Row
  2015-02-03 11:19:31,885,DEBUG,44,After Getting Row
  2015-02-03 11:19:31,947,DEBUG,44,Before Test1
  2015-02-03 11:19:31,947,DEBUG,44,Before Test2
  2015-02-03 11:19:32,103,ERROR,44,Error exporting using template 
  System.ObjectDisposedException: Can not access a closed Stream.
     at System.IO.Compression.DeflateStream.EnsureNotDisposed()
     at MS.Internal.IO.Packaging.CompressStream.Flush()
     at MS.Internal.IO.Zip.ZipIOLocalFileBlock.FlushExposedStreams()
     at MS.Internal.IO.Zip.ZipIOLocalFileBlock.UpdateReferences(Boolean closingFlag)
     at MS.Internal.IO.Zip.ZipIOBlockManager.SaveContainer(Boolean closingFlag)
     at MS.Internal.IO.Zip.ZipIOBlockManager.SaveStream(ZipIOLocalFileBlock blockRequestingFlush, Boolean closingFlag)
     at MS.Internal.IO.Zip.ZipIOModeEnforcingStream.Dispose(Boolean disposing)
     at System.IO.Stream.Close()
     at System.Xml.XmlUtf8RawTextWriter.Close()
     at System.Xml.XmlWellFormedWriter.Close()
     at DocumentFormat.OpenXml.OpenXmlPartRootElement.SaveToPart(OpenXmlPart openXmlPart)
     at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.SavePartContents()
     at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.Dispose(Boolean disposing)
     at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.Dispose()
     at Metrico.DatumBase.BizLogic.ExporterBL.CreateSpreadsheetExportUsingTemplate(DataSet dataSet, String templatePath, String exportPath)
  </code></pre>
  
  <p>Code:</p>
  
  <pre><code>try
  {
      using (SpreadsheetDocument document = SpreadsheetDocument.Open(exportPath, true))
      {
          WorkbookPart workbookPart = document.WorkbookPart;
  
          // Iterate through the DataTables, and populate the existing worksheets with the same names
          for (int i = 1; i &lt; dataSet.Tables.Count; i++)
          {
              // Grab the DataTable/Worksheet name from the first DataTable (like a Table of Contents)
              var worksheetName = dataSet.Tables[0].Rows[i - 1].Field&lt;string&gt;("FriendlyName");
  
              // Get the worksheet that has the same name
              Sheet theSheet = workbookPart.Workbook.Descendants&lt;Sheet&gt;().FirstOrDefault(s =&gt; s.Name == worksheetName);
  
              // Only attempt to process the sheet if it was found in the template
              if (theSheet != null)
              {
                  // Get the worksheet to read from
                  var worksheetPart = (WorksheetPart) workbookPart.GetPartById(theSheet.Id);
                  string originalSheetID = workbookPart.GetIdOfPart(worksheetPart);
  
                  // Make a copy of the worksheet to write to
                  var replacementPart = workbookPart.AddNewPart&lt;WorksheetPart&gt;();
                  string replacementPartID = workbookPart.GetIdOfPart(replacementPart);
  
                  // Create the reader for the original and the writer for the replacement
                  using (var reader = OpenXmlReader.Create(worksheetPart))
                  {
                      using (var writer = OpenXmlWriter.Create(replacementPart))
                      {
                          // Get the cell formats for the first non-header row
                          WorkbookStylesPart stylesPart = workbookPart.GetPartsOfType&lt;WorkbookStylesPart&gt;().First();
                          Logger.Log(LogLevel.Debug, "Before Test1");
                          var test1 = worksheetPart;
                          Logger.Log(LogLevel.Debug, "Before Test2");
                          var test2 = worksheetPart.Worksheet;
                          Logger.Log(LogLevel.Debug, "Before Getting Row");
                          Row firstContentRow = worksheetPart.Worksheet.Descendants&lt;Row&gt;().FirstOrDefault(r =&gt; r.RowIndex == 2);
                          Logger.Log(LogLevel.Debug, "After Getting Row");
                          Dictionary&lt;string, uint&gt; columnFormats = GetCellFormats(firstContentRow);
                          // Create a DateTime cell format style
                          var dateFormat = new CellFormat
                          {
                              NumberFormatId = UInt32Value.FromUInt32(22),
                              ApplyNumberFormat = BooleanValue.FromBoolean(true)
                          };
                          stylesPart.Stylesheet.CellFormats.Append(dateFormat);
                          UInt32Value dateStyleIndex = stylesPart.Stylesheet.CellFormats.Count;
                          stylesPart.Stylesheet.CellFormats.Count++;
  
                          // Read from the template worksheet and write to the new worksheet
                          while (reader.Read())
                          {
                              // We only care about altering the contents of the SheetData element
                              if (reader.ElementType == typeof (SheetData))
                              {
                                  if (reader.IsEndElement)
                                  {
                                      continue;
                                  }
  
                                  // Write the start of the SheetData element
                                  writer.WriteStartElement(new SheetData());
  
                                  // Add column names to the first Excel row
                                  var headerRow = new Row();
                                  foreach (DataColumn column in dataSet.Tables[i].Columns)
                                  {
                                      var headerCell = CreateTextCell(
                                          dataSet.Tables[i].Columns.IndexOf(column) + 1, 1, column.ColumnName, null);
                                      headerRow.Append(headerCell);
                                  }
                                  // Write the head row element
                                  writer.WriteElement(headerRow);
  
                                  // Loop through each DataRow and populate the corresponding Excel row
                                  for (int j = 0; j &lt; dataSet.Tables[i].Rows.Count; j++)
                                  {
                                      var contentRow = dataSet.Tables[i].Rows[j];
  
                                      Row row = CreateContentRow(contentRow, j + 2, columnFormats, dateStyleIndex);
  
                                      // Write the row element
                                      writer.WriteElement(row);
  
                                  }
  
                                  // Write the end of the SheetData element
                                  writer.WriteEndElement();
                              }
                              else
                              {
                                  // Automatically copy over all other elements
                                  if (reader.IsStartElement)
                                  {
                                      writer.WriteStartElement(reader);
                                  }
                                  else if (reader.IsEndElement)
                                  {
                                      writer.WriteEndElement();
                                  }
                              }
                          }
                      }
                  }
  
                  // Point the workbook to the new sheet and delete the old one
                  Sheet sheet = workbookPart.Workbook.Descendants&lt;Sheet&gt;().First(s =&gt; s.Id.Value.Equals(originalSheetID));
                  sheet.Id.Value = replacementPartID;
                  workbookPart.DeletePart(worksheetPart);
              }
          }
  
          //This section will remove data from sheets that have not been populated, leaving the header row intact
          List&lt;string&gt; emptyTasks = new List&lt;string&gt;
          {
              "task",
          };
  
          var currentTasks =
              dataSet.Tables[0].AsEnumerable()
                  .Select(x =&gt; x.Field&lt;string&gt;("FriendlyName").ToString(CultureInfo.InvariantCulture))
                  .ToList();
  
          foreach (string task in currentTasks.Where(emptyTasks.Contains))
          {
              emptyTasks.Remove(task);
          }
  
          foreach (string task in emptyTasks)
          {
              Sheet theSheet = workbookPart.Workbook.Descendants&lt;Sheet&gt;().FirstOrDefault(s =&gt; s.Name == task);
              if (theSheet != null)
              {
                  WorksheetPart worksheetPart = (WorksheetPart) workbookPart.GetPartById(theSheet.Id);
  
                  SheetData sheetData = worksheetPart.Worksheet.GetFirstChild&lt;SheetData&gt;();
  
                  sheetData.Elements&lt;Row&gt;().Where(r =&gt; r.RowIndex &gt; 1).ToList().ForEach(x =&gt; x.Remove());
                  theSheet.Elements&lt;Row&gt;().ToList().ForEach(x =&gt; x.Remove());
  
                  worksheetPart.Worksheet.Save();
              }
          }
  
          workbookPart.Workbook.CalculationProperties.ForceFullCalculation = true;
          workbookPart.Workbook.CalculationProperties.FullCalculationOnLoad = true;
      }
  }
  catch (Exception ex)
  {
      Logger.Log(LogLevel.Error, "Error exporting using template ", ex);
      throw;
  }
  </code></pre>
  
  <p>As you can see it runs through this loop several times successfully, then it seems to just break when accessing a worksheet? WTF? This doesn't seem to happen on every server either. Any thoughts appreciated as I am out of ideas.</p>
  
  <p>Also of note: It seems that something is keeping a lock on this file even after the exception is thrown. If I try to copy the file I get: The action can't be completed because the file is open in w3wp.exe." So somehow the document isn't getting disposed either?</p>
  
  <p>Changing the app pool to "LocalSystem" prevents an exception from being thrown but instead causes the system to just lock up. It fails at the exact same spot but does not throw an exception and does not get any farther in the process (the file is the exact same size as the other failed files and the log is the same).</p>
  
  <p>Moving the try/catch into the using statement exposes a new exception:</p>
  
  <pre><code>2015-02-04 09:45:23,577,ERROR,6,Error exporting using template 
  System.IO.IsolatedStorage.IsolatedStorageException: Unable to create mutex. (Exception from HRESULT: 0x80131464)
     at System.IO.IsolatedStorage.IsolatedStorageFile.Open(String infoFile, String syncName)
     at System.IO.IsolatedStorage.IsolatedStorageFile.Lock(Boolean&amp; locked)
     at System.IO.IsolatedStorage.IsolatedStorageFileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, IsolatedStorageFile isf)
     at System.IO.IsolatedStorage.IsolatedStorageFileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, IsolatedStorageFile isf)
     at MS.Internal.IO.Packaging.PackagingUtilities.SafeIsolatedStorageFileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, ReliableIsolatedStorageFileFolder folder)
     at MS.Internal.IO.Packaging.PackagingUtilities.CreateUserScopedIsolatedStorageFileStreamWithRandomName(Int32 retryCount, String&amp; fileName)
     at MS.Internal.IO.Packaging.SparseMemoryStream.EnsureIsolatedStoreStream()
     at MS.Internal.IO.Packaging.SparseMemoryStream.SwitchModeIfNecessary()
     at MS.Internal.IO.Packaging.DeflateEmulationTransform.Decompress(Stream source, Stream sink)
     at MS.Internal.IO.Packaging.CompressEmulationStream..ctor(Stream baseStream, Stream tempStream, Int64 position, IDeflateTransform transformer)
     at MS.Internal.IO.Packaging.CompressStream.ChangeMode(Mode newMode)
     at MS.Internal.IO.Packaging.CompressStream.Seek(Int64 offset, SeekOrigin origin)
     at MS.Internal.IO.Zip.ZipIOModeEnforcingStream.Read(Byte[] buffer, Int32 offset, Int32 count)
     at System.Xml.XmlTextReaderImpl.InitStreamInput(Uri baseUri, String baseUriStr, Stream stream, Byte[] bytes, Int32 byteCount, Encoding encoding)
     at System.Xml.XmlTextReaderImpl.FinishInitStream()
     at System.Xml.XmlReaderSettings.CreateReader(Stream input, Uri baseUri, String baseUriString, XmlParserContext inputContext)
     at DocumentFormat.OpenXml.OpenXmlPartRootElement.LoadFromPart(OpenXmlPart openXmlPart, Stream partStream)
     at DocumentFormat.OpenXml.Packaging.OpenXmlPart.LoadDomTree[T]()
     at DocumentFormat.OpenXml.Packaging.WorksheetPart.get_Worksheet()
     at Metrico.DatumBase.BizLogic.ExporterBL.CreateSpreadsheetExportUsingTemplate(DataSet dataSet, String templatePath, String exportPath)
  </code></pre>