Filtering with Fallback Recovery

Avatar of Hemanta SundarayHemanta Sundaray

HttpClient.filterOrElse() is the recovery-oriented counterpart to filterOrFail. Instead of producing an error when the predicate fails, it runs an alternative effect that can return a different response.

This is useful when you want to transparently handle certain response conditions, like falling back to a cached response, retrying with different parameters, or transforming an unexpected response into an expected one.

http.ts
import {
FetchHttpClient,
HttpClient,
HttpClientRequest,
} from "effect/unstable/http";
import { Effect } from "effect";
function fetchProductWithFallback(productId: number) {
return Effect.gen(function* () {
const client = (yield* HttpClient.HttpClient).pipe(
// If the response isn't a 200, fall back to product 1
HttpClient.filterOrElse(
(response) => response.status === 200,
(response) =>
Effect.gen(function* () {
console.log(
`Got status ${response.status}, falling back to product 1`,
);
const fallbackClient = yield* HttpClient.HttpClient;
return yield* fallbackClient.get(
"https://dummyjson.com/products/1",
);
}),
),
);
const request = HttpClientRequest.get(
`https://dummyjson.com/products/${productId}`,
);
const response = yield* client.execute(request);
const product = yield* response.json;
return product;
}).pipe(Effect.provide(FetchHttpClient.layer));
}
// Test with a valid product
Effect.runPromise(fetchProductWithFallback(1)).then((product) => {
console.log("Product:", product.title);
});
// Test with an invalid product — falls back to product 1
Effect.runPromise(fetchProductWithFallback(99999)).then((product) => {
console.log("Product:", product.title);
});

Output:

Terminal
Product: Essence Mascara Lash Princess
Got status 404, falling back to product 1
Product: Essence Mascara Lash Princess

The first argument is the same predicate as filterOrFail. The difference is the second argument: instead of an error constructor, it’s a function that returns an Effect<HttpClientResponse>. This effect can do anything: make another request, return a cached response, or even succeed with the original response after logging.

The key distinction between the two:

  • filterOrFail: Predicate fails → error in the error channel. The caller must handle it.
  • filterOrElse: Predicate fails → alternative effect runs. The caller doesn’t know the filter was triggered.

Use filterOrFail when a bad response is an error your application needs to know about. Use filterOrElse when you can transparently recover and the caller doesn’t need to care.

Sign in to save progress

Stay in the loop

Get notified when new chapters are added and when this course is complete.