Table of Contents

TRLS015 — Don't throw exceptions in Result chains

  • Severity: Warning
  • Category: Trellis

What it detects

Flags throw statements and throw expressions inside lambdas passed to Trellis chain methods such as Bind, Map, Tap, Ensure, and their async and failure-track variants.

Why it matters

Throwing inside a Result pipeline bypasses the railway and turns a modeled failure back into an exception.

Warning

This rule also applies to failure-track APIs like TapOnFailure, MapOnFailure, RecoverOnFailure, and DebugOnFailure.

Bad example

using System;
using Trellis;

static class Example
{
    public static Result<string> Bad(string value) =>
        Result.Success(value).Map(text =>
        {
            if (string.IsNullOrWhiteSpace(text))
                throw new InvalidOperationException("Value is required.");

            return text.Trim();
        });
}

Good example

using System;
using Trellis;

static class Example
{
    public static Result<string> Good(string value) =>
        Result.Success(value).Bind(text =>
        {
            if (string.IsNullOrWhiteSpace(text))
                return Result.Failure<string>(Error.Validation("Value is required.", nameof(value)));

            return Result.Success(text.Trim());
        });
}

Code fix available

No.

Configuration

Use standard Roslyn configuration if you need to suppress this rule in a specific scope.

dotnet_diagnostic.TRLS015.severity = none
#pragma warning disable TRLS015
// Intentional: documented exception or test-only pattern.
#pragma warning restore TRLS015
Tip

Return Result.Failure<T>(...) when the callback discovers a business or validation problem. Reserve exceptions for truly exceptional situations.