File System File System
File System File System
DocFX + Singulink = ♥

Search Results for

    Exception Handling

    The library is designed to make exception handling boringly predictable: parsing throws ArgumentException, file system operations throw IOException, and nothing else needs to be accounted for. That separation lets you write tidy try/catch blocks without resorting to catch (Exception) to corral the mix of unrelated exception types System.IO would otherwise throw.

    The Two Exception Families

    • Parsing throws ArgumentException (and subtypes). Every input-validation error during path construction comes from this family.
    • I/O throws IOException (and subtypes). Every error from a file system operation comes from this family, including permission errors, which are surfaced as UnauthorizedIOAccessException (a subclass of IOException).

    Parse-Time Errors

    ArgumentException (or ArgumentNullException / ArgumentOutOfRangeException for null or invalid arguments) is the only exception family thrown by parsing and path-manipulation methods. Catch it where you accept untrusted input:

    IFilePath file;
    try
    {
        file = FilePath.Parse(userInput);
    }
    catch (ArgumentException ex)
    {
        log.Warn($"Invalid path: {ex.Message}");
        return;
    }
    

    Exception messages are detailed enough to act on directly. They name the exact rule that failed (e.g. "Entry name ends with a dot.", "Attempt to navigate past root directory.").

    Parsing Without Exceptions

    When invalid input is a routine outcome and you don't need the reason, skip the exception entirely with the Try parse methods: FilePath.TryParse, FilePath.TryParseAbsolute, FilePath.TryParseRelative and their DirectoryPath equivalents. They return false instead of throwing:

    if (!FilePath.TryParse(userInput, out IFilePath? file))
    {
        log.Warn("Invalid path.");
        return;
    }
    
    Tip

    The Try methods don't say why the input was rejected. If you want to show the user the specific rule that failed, parse with the throwing method and report the exception message as in the first example. See Parsing Paths.

    I/O-Time Errors

    Every method that touches the file system throws only IOException and its subtypes, across both Windows and Unix. The full set you can encounter:

    Exception Typical cause
    FileNotFoundException A file expected to exist is missing.
    DirectoryNotFoundException A directory expected to exist is missing.
    PathTooLongException The fully-qualified path exceeds the OS limit.
    UnauthorizedIOAccessException The OS denied access.
    IOException Anything else (file in use, disk full, network failure, etc.).

    A single base-type catch handles all of them:

    try
    {
        using FileStream s = file.OpenStream(FileMode.Open, FileAccess.Read, FileShare.Read);
        return Read(s);
    }
    catch (IOException ex)
    {
        log.Warn($"Could not read {file.PathDisplay}: {ex.Message}");
        return null;
    }
    

    UnauthorizedIOAccessException

    System.IO surfaces permission errors as UnauthorizedAccessException, which does not derive from IOException. That forces you to catch two unrelated base types to handle "any I/O failure".

    This library raises UnauthorizedIOAccessException instead (a direct IOException subclass), so a single catch (IOException) covers every failure mode. If you specifically need to distinguish access denial:

    try
    {
        file.Delete();
    }
    catch (UnauthorizedIOAccessException) { /* show "permission denied" UI */ }
    catch (IOException)                    { /* something else went wrong */ }
    
    Note

    The library converts UnauthorizedAccessException thrown by underlying System.IO calls into UnauthorizedIOAccessException. You should never need to catch UnauthorizedAccessException from this library's surface.

    Cross-Platform Consistency

    System.IO throws different exception types on Windows and Unix for the same operation. For example, File.Delete on a directory throws UnauthorizedAccessException on Windows but IOException on Unix. This library normalizes those: the exception type for a given failure is the same across platforms.

    Important

    If you're catching specific exception types in code that needs to behave the same on Windows and Unix, use this library's surface; System.IO's exception types are not portable.

    Search-Time Errors

    Enumeration is lazy. Exceptions can be thrown during the iteration of a foreach, not just from the call that produced the enumerable. Catch around the iteration site:

    try
    {
        foreach (var f in dir.GetChildFiles("*", new SearchOptions { Recursive = true }))
            Process(f);
    }
    catch (UnauthorizedIOAccessException ex)
    {
        log.Warn($"Search hit a forbidden directory: {ex.Message}");
    }
    

    The behavior on inaccessible directories is configurable. See Searching and Enumeration and InaccessibleSearchBehavior.

    Putting It Together

    A typical input-handling pattern that keeps parsing and I/O concerns clean:

    // Phase 1: validate input. Only ArgumentException is possible here.
    IAbsoluteFilePath file;
    try
    {
        file = FilePath.ParseAbsolute(userInput);
    }
    catch (ArgumentException ex)
    {
        return Result.Invalid(ex.Message);
    }
    
    // Phase 2: do I/O. Only IOException family is possible here.
    try
    {
        using FileStream s = file.OpenStream(FileMode.Open, FileAccess.Read, FileShare.Read);
        return Result.Ok(Read(s));
    }
    catch (FileNotFoundException)             { return Result.NotFound(); }
    catch (UnauthorizedIOAccessException ex)  { return Result.Forbidden(ex.Message); }
    catch (IOException ex)                    { return Result.Error(ex.Message); }
    

    Next Steps

    The operations behind these exceptions are covered in:

    • Parsing Paths: the throwing and non-throwing parse methods.
    • Searching and Enumeration: search-time error handling and InaccessibleSearchBehavior.
    • Working with Files and Working with Directories: the operations covered by the I/O-side catches.
    © Singulink. All rights reserved.