For the complete documentation index, see llms.txt. This page is also available as Markdown.

Errors

Build the failure value you put inside an Err.

You have decided a method returns Result<T, E>. Now you need something to put in the E.

You can use any type you like — a string, your own record, an enum. This page is about the two types the library ships for when you would rather not write your own.

Looking for what the library throws at you? That is Exceptions.

The two types

public record ErrorCode
{
    public ErrorCode(string value);

    public string Value { get; }
}

public record Error
{
    public Error(ErrorCode code, string message);

    public ErrorCode Code { get; }
    public string Message { get; }
}

An ErrorCode is a short, stable identifier for a kind of failure. An Error is one occurrence of it, with a message a human can read.

Two details that trip people up:

  • Error names its code property Code, not ErrorCode. Read it as error.Code.Value.

  • Both types declare their constructor explicitly rather than positionally. So you cannot deconstruct them, and you cannot use with to change a property. Build a new instance instead.

Define your error codes

An error code should not change between one occurrence of a failure and the next. That means defining them up front, not building them at the call site.

The simplest thing that works. A static class holding every code your application can produce — in your domain layer, if you are following domain-driven design.

Start here. If you outgrow it, the next section is where to go.

From an enum

If you would rather group codes as an enum, mark it [ErrorCodeCatalog] and the source generator writes the codes for you:

This is a generated API with more to it than one line — the naming format, the ToErrorCode() extension for when you only know the member at run time, the using it needs. See Generated error codes.

Build an error

Two occurrences, one code. That is the split working as intended: the code is what you branch on and log against, the message is what you show a person.

You need an ErrorCode before you can build an Error. There is no message-only constructor.

From a catalog enum

If your codes come from a [ErrorCodeCatalog] enum, the generated Errors factory builds the whole Error in one call:

The message is required here, unlike the code-only form. An Error always carries one.

To turn that straight into a Result, pass it to Result.Err:

From an exception you caught

Both types convert from an exception you already hold, for when you are at a boundary and want a Result rather than a rethrow. That lives on the other page, next to the exceptions themselves — see From an exception you caught.

Where to go next

Last updated

Was this helpful?