Decode your feedbackDecode: errors as values, not warnings
No narration yet
Module 12 · Lesson 213 min

Decode: errors as values, not warnings

The Nest reflex for a missing row is throw new NotFoundException(). Fusion models failure as data, and two of Rai's reviews pushed exactly on that shift.

The comment (Sergii Volodko, PR #401, on GetFlights.cs):

"We shouldn't consider all errors as warnings. Instead, I'd introduce a new error type, like FlightNotFound, and then when catching errors on DB access layer produce those errors in result, after that on the application level, we can distinguish them by type and place into warnings."

And (Sergii, same PR, on GetFlightsResponse.cs):

"a small design smell here, Response is currently an API presentation term, but we add it here on the application level ... instead of introducing intermediate nested classes like this one, we need to create an extension of our Result: ResultWithWarnings?"

What he meant. Two things. First, typed errors carry domain meaning. When a DB read fails, don't flatten it into a generic "warning"; return a typed error (FlightNotFound) that a caller can pattern-match to decide a 404 versus a 504 versus a soft warning. The distinction the domain cares about should live in the type system, not in a status string or a boolean. Second, don't let a layer's vocabulary leak downward. Response is a presentation word; naming an application-layer type Response mixes the layers. Express the concept as a domain-level Result extension instead. That's the ubiquitous-language discipline (Module 8's Result, Module 11's naming) applied to errors.

From warning-soup to typed errors
// What Sergii pushed against: every failure becomes an untyped warning.
result.Warnings.Add("could not load flight");

// The shift: a typed error the endpoint can map by type (Module 5's switch).
public sealed record FlightNotFound(string Field, string Message) : EjError(Field, Message);

return Result<FlightsView>.Failure(new FlightNotFound(nameof(key), "No flight for key."));

The convention doc (D5/E2, from Nick and Sergii on earlier PRs) states the downstream rule:

"Branch on Result type, not domain status values. Endpoints use result.IsSuccess and pattern-match on error types (EntityNotFound, DecisionNotFound). They never inspect domain-specific status strings like result.Status == \"reverted\"."

Practice

Try it yourself

Recall

Why a typed error beats a warning

Explain Sergii's push in DDD terms.

Sergii asked Rai to introduce a FlightNotFound error type instead of treating every DB-access failure as a warning. What does the typed error let a caller do that a generic warning does not?

Quiz

The layering smell in a name

Sergii flagged an application-layer class named GetFlightsResponse and suggested a Result extension instead. What was the smell?