esteban@devtrillo:~/blog/writing$
← cd -
$ cat learning-effect-6-catch-one-error-not-the-world.md

Part 6: Catch One Error, Not the World

Jul 15, 2026·1 min read
$ tail -f learning-effect-6-catch-one-error-not-the-world/readers
connecting…

try/catch is often too wide.

You want to handle one known failure. But the catch block can grab everything.

That is how bugs get hidden.

Effect gives you a smaller move: catchTag.

Handle one error

const program = fetchUser(1).pipe(
Effect.catchTag("UserNotFound", () =>
Effect.succeed({ id: 1, name: "Guest" }),
),
);

This handles UserNotFound.

It does not mean every possible error is gone.

What does catchTag('UserNotFound', ...) handle?

The error slot gets smaller

Before:

Effect.Effect<User, UserNotFound | DatabaseDown, UserRepo>;

After handling UserNotFound:

Effect.Effect<User, DatabaseDown, UserRepo>;

That is the win.

The type changes because the program changed.

After handling UserNotFound, which error can still remain?

Do not catch what you cannot fix

This is the part I care about.

If I can turn UserNotFound into a guest user, fine.

If the database is down, I probably should not pretend everything is okay.

NOTE

Catch the error you understand. Let the type keep yelling about the ones you do not.