Handling errors

edit

The library reports each kind of failure with its own exception, so your code can tell a file that is not an image from a corrupted one, a feature the library does not support from a limit your configuration set.

Catch the content errors

When you load files you do not control, catch the exceptions that describe the input:

public static Image? TryLoad(string path, ImageConfiguration configuration)
{
    try
    {
        return Image.Load(path, new ImageDecodeOptions { Configuration = configuration });
    }
    catch (UnknownImageFormatException)
    {
        return null; // not an image
    }
    catch (UnsupportedImageFeatureException ex)
    {
        Console.Error.WriteLine($"Unsupported {ex.Format} feature: {ex.Feature}");
        return null;
    }
    catch (ImageResourceLimitException ex)
    {
        Console.Error.WriteLine($"Limit {ex.Kind} exceeded ({ex.Requested} > {ex.Limit})");
        return null;
    }
    catch (InvalidImageContentException)
    {
        return null; // corrupted or truncated file
    }
}

These exceptions derive from ImageException, which you can catch to handle them all at once:

ExceptionMeaning
UnknownImageFormatExceptionThe content is not recognized as an image format.
InvalidImageContentExceptionThe format is recognized, but the data is malformed, inconsistent or truncated. Also thrown when you save a malformed EXIF, ICC or XMP payload. Format tells the format.
UnsupportedImageFeatureExceptionThe data uses a valid feature that the library does not support (a hierarchical JPEG, for example), or an operation would lose information without an explicit setting: an animation, transparency, precision, metadata, a cursor hotspot, a poster frame, a color profile, a duration or a play count the output cannot store. Format and Feature tell what.
ImageResourceLimitExceptionA resource limit was exceeded. Kind, Limit and Requested tell which one and by how much.

A malformed or truncated input always throws: it is never reported as the clean end of an animation, and never returns a partial image.

Accept the files browsers accept

Some files in the wild break their specification in ways that browsers and the reference decoders tolerate: a GIF without its trailer, for example. By default the library rejects them with an InvalidImageContentException. To load them, read them leniently:

public static Image LoadLeniently(string path)
{
    var configuration = new ImageConfiguration { DecodingStrictness = DecodingStrictness.Lenient };
    return Image.Load(path, new ImageDecodeOptions { Configuration = configuration });
}

The lenient mode accepts a fixed list of deviations, given on the page of each format, and repairs them the way the reference decoders do. Everything else stays the same:

  • The resource limits apply exactly as they do in the strict mode.
  • A file that could only be repaired by guessing pixels is still rejected.
  • It applies to Identify, Load, the readers and the collections, so they agree on which files they accept.

The other exceptions

The other failures use the standard .NET exceptions:

ExceptionMeaning
ArgumentException and derived typesAn invalid argument: a file extension Save does not know, frames of different sizes, a stream that cannot be read or written, …
NotSupportedExceptionA pixel type that is not one of the pixel formats, thrown before any I/O
InvalidOperationExceptionAn invalid state: a conflicting lease, overlapping calls to a reader or a writer, a call to a reader or a writer that failed before
ObjectDisposedExceptionA disposed image, or a frame that was removed or whose image was disposed
OperationCanceledExceptionThe operation was canceled
IOExceptionThe file or the stream failed, passed on unchanged

These usually point at a bug in the calling code or at the environment, not at the input: let them propagate.

What to catch where

The messages of the exceptions are meant for people and may change between versions: test the type and the properties, not the message.