Magick.NET version
14.16
Environment (Operating system, version and so on)
Windows 11
Description
Writing a multi‑frame MagickImageCollection to a TIFF via the async file overloads (WriteAsync(FileInfo) / WriteAsync(string)) throws:
ImageMagick.MagickCoderErrorException : Error fetching directory count. `TIFFLinkDirectory' @ error/tiff.c/TIFFErrors/564
The synchronous Write(...) works fine, and so does WriteAsync(Stream) when the stream is readable/seekable. The failure is limited to the async file path and only when the collection has more than one frame (i.e., a multi‑directory TIFF).
Steps to Reproduce
The assets/ folder contains the two inputs:
File | Frames
-- | --
assets/single-page.tif | 1
assets/multi-page.tif | 56
Program.cs exposes two methods:
RunSinglePageAsync(...) — loads single-page.tif, tries Write and WriteAsync.RunMultiPageAsync(...) — loads multi-page.tif, tries Write, WriteAsync(FileInfo) and WriteAsync(Stream).
To compare versions, change the single line in ImageMagickTest.csproj:
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="14.16.0" /> <!-- fails -->
<!-- <PackageReference Include="Magick.NET-Q8-AnyCPU" Version="14.13.1" /> works -->
Verified output
14.16.0 (libtiff 4.7.2) — FAILS
Magick.NET Q8 AnyCPU net8.0 14.16.0
== Single-page: single-page.tif ==
frames = 1
Write(file) OK
WriteAsync(file) OK
== Multi-page: multi-page.tif ==
frames = 56
Write(file) OK
WriteAsync(file) FAIL -> MagickCoderErrorException: Error fetching directory count. `TIFFLinkDirectory' @ error/tiff.c/TIFFErrors/564
WriteAsync(stream) OK
14.13.1 (libtiff 4.7.1) — WORKS
Magick.NET Q8 AnyCPU net8.0 14.13.1
== Single-page: single-page.tif ==
frames = 1
Write(file) OK
WriteAsync(file) OK
== Multi-page: multi-page.tif ==
frames = 56
Write(file) OK
WriteAsync(file) OK
WriteAsync(stream) OK
Why WriteAsync fails (root cause)
A multi-page TIFF stores each page as an IFD (Image File Directory). When writing the 2nd and later pages, libtiff calls TIFFLinkDirectory() to link the new directory into the chain.
In libtiff 4.7.2, TIFFLinkDirectory() was changed to detect IFD loops. To do that it now walks / reads back the already-written output to fetch the existing directory count. That read-back is what emits:
Error fetching directory count. `TIFFLinkDirectory' @ error/tiff.c/TIFFErrors/564
The problem is the stream the output is being written to must be readable for that read-back to succeed:
Write(FileInfo) (sync) → hands the filename to native libtiff, which opens the file itself with read/write access → read-back works → ✅WriteAsync(Stream) with a readable stream (File.Create opens ReadWrite, or a MemoryStream) → read-back works → ✅WriteAsync(FileInfo) / WriteAsync(string) → Magick.NET's async file path (WriteAsyncInternal(fileName) → WriteAsync(Stream)) opens the destination file as a write-only stream → the new read-back has no read access → ❌
Single-page TIFFs have only one IFD, so TIFFLinkDirectory() is never called — which is why they succeed on every path and every version.
Call stack (14.16.0)
ImageMagick.NativeHelper.CheckException(...)
ImageMagick.MagickImageCollection.NativeMagickImageCollection.WriteStream(...)
ImageMagick.MagickImageCollection.<>c__DisplayClass158_0.<WriteAsync>b__0()
ImageMagick.AsyncStreamWrapper.WriteAsync(...)
ImageMagick.MagickImageCollection.WriteAsync(Stream, CancellationToken)
ImageMagick.MagickImageCollection.WriteAsync(Stream, MagickFormat, CancellationToken)
ImageMagick.MagickImageCollection.WriteAsyncInternal(String fileName, Nullable<MagickFormat>, CancellationToken)
ImageMagick.MagickImageCollection.WriteAsync(FileInfo file)
Images

Magick.NET version
14.16
Environment (Operating system, version and so on)
Windows 11
Description
Writing a multi‑frame MagickImageCollection to a TIFF via the async file overloads (WriteAsync(FileInfo) / WriteAsync(string)) throws:
ImageMagick.MagickCoderErrorException : Error fetching directory count. `TIFFLinkDirectory' @ error/tiff.c/TIFFErrors/564The synchronous Write(...) works fine, and so does WriteAsync(Stream) when the stream is readable/seekable. The failure is limited to the async file path and only when the collection has more than one frame (i.e., a multi‑directory TIFF).
Steps to Reproduce
The
File | Frames -- | -- assets/single-page.tif | 1 assets/multi-page.tif | 56assets/folder contains the two inputs:Program.csexposes two methods:RunSinglePageAsync(...)— loadssingle-page.tif, triesWriteandWriteAsync.RunMultiPageAsync(...)— loadsmulti-page.tif, triesWrite,WriteAsync(FileInfo)andWriteAsync(Stream).To compare versions, change the single line in
ImageMagickTest.csproj:Verified output
14.16.0 (libtiff 4.7.2) — FAILS
14.13.1 (libtiff 4.7.1) — WORKS
Why
WriteAsyncfails (root cause)A multi-page TIFF stores each page as an IFD (Image File Directory). When writing the 2nd and later pages, libtiff calls
TIFFLinkDirectory()to link the new directory into the chain.In libtiff 4.7.2,
TIFFLinkDirectory()was changed to detect IFD loops. To do that it now walks / reads back the already-written output to fetch the existing directory count. That read-back is what emits:The problem is the stream the output is being written to must be readable for that read-back to succeed:
Write(FileInfo)(sync) → hands the filename to native libtiff, which opens the file itself with read/write access → read-back works → ✅WriteAsync(Stream)with a readable stream (File.CreateopensReadWrite, or aMemoryStream) → read-back works → ✅WriteAsync(FileInfo)/WriteAsync(string)→ Magick.NET's async file path (WriteAsyncInternal(fileName)→WriteAsync(Stream)) opens the destination file as a write-only stream → the new read-back has no read access → ❌Single-page TIFFs have only one IFD, so
TIFFLinkDirectory()is never called — which is why they succeed on every path and every version.Call stack (14.16.0)
Images