Catching Specific Error Types

Avatar of Hemanta SundarayHemanta Sundaray

HttpClient.catchTag() catches only errors with a specific _tag, letting other error types pass through.

This is useful when your client’s error channel contains multiple error types. For example, if you use schema validation on responses, the error channel includes both HttpClientError (from the HTTP request) and SchemaError (from validation). catchTag lets you recover from one while letting the other propagate.

http.ts
import {
FetchHttpClient,
HttpClient,
HttpClientRequest,
HttpClientResponse,
} from "effect/unstable/http";
import { Effect, Schema } from "effect";
const User = Schema.Struct({
id: Schema.Number,
firstName: Schema.String,
lastName: Schema.String,
});
function fetchUser(userId: number) {
return Effect.gen(function* () {
const client = (yield* HttpClient.HttpClient).pipe(
HttpClient.filterStatusOk,
// Only catch HttpClientError (network failures, bad status codes, etc.)
// SchemaError from validation is NOT caught — it will still propagate
HttpClient.catchTag("HttpClientError", (error) =>
Effect.gen(function* () {
console.log(`HTTP error: ${error.message}`);
console.log("Falling back to default user...");
const fallbackClient = yield* HttpClient.HttpClient;
return yield* fallbackClient.get("https://dummyjson.com/users/1");
}),
),
);
const request = HttpClientRequest.get(
`https://dummyjson.com/users/${userId}`,
);
const response = yield* client.execute(request);
// This can fail with SchemaError, which is NOT caught by catchTag above
const user = yield* HttpClientResponse.schemaBodyJson(User)(response);
return user;
}).pipe(Effect.provide(FetchHttpClient.layer));
}
// Test with an invalid user — HttpClientError is caught, fallback is used
Effect.runPromise(fetchUser(9999)).then(
(user) => console.log("User:", user.firstName, user.lastName),
(error) => console.error(`[${error._tag}] ${error.message}`),
);

Output:

Terminal
HTTP error: StatusCode: non 2xx status code (404 GET https://dummyjson.com/users/9999)
Falling back to default user...
User: Emily Johnson

All HTTP client errors share a single type: HttpClientError (with _tag: "HttpClientError"). The specific failure kind — transport error, status code error, decode error, etc. — is in the error.reason._tag field. This means catchTag("HttpClientError", ...) catches all HTTP-related errors.

The power of catchTag shows when other error types are in the channel. In this example, a SchemaError from schemaBodyJson would bypass the catchTag handler entirely and propagate to the caller. This lets you be precise: recover from HTTP failures (server down, bad status code) while still surfacing data integrity issues (unexpected response shape) as errors that need attention.

If your client only produces HttpClientError and you want to catch everything, HttpClient.catch is simpler. Reach for catchTag when multiple error types are in play and you need selective recovery.

Sign in to save progress

Stay in the loop

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