Table of Contents

TRLS010 — 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.Ok(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.Ok(value).Bind(text =>
        {
            if (string.IsNullOrWhiteSpace(text))
                return Result.Fail<string>(new Error.UnprocessableContent(EquatableArray.Create(new FieldViolation(InputPointer.ForProperty(nameof(value)), "validation.error") { Detail = "Value is required." })));

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

Code fix available

No.

Configuration

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

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

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