← All articles

Translating service failures at the boundary

An empty service response is different from a service that never responded. Mapping both to null hides failures behind a no-data screen.

t.Turgay
Translating service failures at the boundary

A null result from a service is not the same as a timed-out connection. Turning both into an empty object can make the screen claim that no record exists when the application never reached its data source. A service adapter should translate provider behavior into outcomes the application can reason about.

Translation is not blanket exception swallowing

This independent .NET 10 console example uses a small Result<T> record to demonstrate the boundary. It needs neither a real HTTP client nor a WCF proxy. The three outcomes are a value, an empty result and an explicitly recognized timeout.

static Result<T> Translate<T>(Func<T?> call) where T:class
{
    try { var value=call(); return value is null ? new("empty",null) : new("ok",value); }
    catch(TimeoutException) { return new("timeout",null); }
}
Console.WriteLine(Translate<string>(()=>null).Status);
Console.WriteLine(Translate<string>(()=>throw new TimeoutException()).Status);
record Result<T>(string Status,T? Value);

The first call prints empty and the second prints timeout. A successful value receives ok. Only TimeoutException is caught; an unrelated exception does not silently become missing data. That is an important distinction between handling an expected integration failure and hiding a programming defect.

Decide what absence means in each use case

An empty search result is normally successful. A lookup for one resource may instead need a not-found outcome. A provider's null can mean absence, a malformed reply or a parsing failure depending on its contract. A low-level helper should not assign the same HTTP meaning to every operation without understanding the use case.

A larger application can replace unconstrained status strings with a closed result model. Data, user-facing messages, field errors and stable application error codes have different responsibilities. The controller translates the service outcome into HTTP; the business service does not need to return transport-specific response objects.

Verify the actual client's failure behavior

TimeoutException is a deliberate simplification here. HttpClient, provider SDKs and WCF do not necessarily report equivalent failures through the same exception type. Asynchronous cancellation and timeout can also appear similar. Propagate and inspect the caller's cancellation token so an intentional cancellation is not automatically reported as a slow provider.

Set timeouts against the whole operation's budget. Three sequential calls with generous individual timeouts can produce an unreasonable total wait. Connection setup, responses and any retries need to fit the time the use case can actually tolerate.

A retry can repeat a completed operation

Retrying a read differs from resubmitting a command that creates an application or another business record. The provider may finish the work even when its response is lost. No response does not prove that no write occurred. An idempotency key or queryable operation identity is needed before adding automatic retries to such commands.

Unexpected failures can reach the application's central exception boundary. The user should receive a useful safe message rather than internal exception text. A correlation identifier is often a sufficient starting point for diagnosis; placing tokens, full request bodies or personal records into an error response does not improve the failure contract.

Map outcomes into meaningful HTTP statuses

A successful empty list can remain 200, an absent individual record can be 404, validation can be 400 and a concurrency conflict can be 409. Provider failure mappings should be consistent with the application's gateway or availability contract. Authentication and authorization also stay distinct: 401 and 403 should not both produce the same login loop.

Test a populated result, null, a timeout, caller cancellation and an unexpected exception separately. The central UI requirement is that a failed call must not produce a success notification or discard an edit the user may need to retry.

HttpClient behavior; API error contracts.

✳ You have reached the end of this orbit.
Explore more articles →
turgay.A little code, a few pixels, a lot of curiosity.© 2026 · Made on Earth ✳