Search code examples
jsonscalacircehttp4szio

Scala, Circe, Http4s - is it any way to encode Throwable in Circe?


I have created hierarchy of errors:

sealed trait MyError extends Throwable
final case class SecondError(msg: String) extends MyError

Now I could get this kind of error in my http4s routes:

case GET -> Root / "things" => for {
        response <- things.all.foldM(
          error => error match {
            case SecondError(_) => InternalServerError(error)            
          }
...

But I get compiled error:

could not find implicit value for parameter encoder: io.circe.Encoder[Throwable]

Is it possible to encode Throwable with circe and http4s? I tried to do it this way:

implicit def encoderHttpThrowable: EntityEncoder[Env, Throwable] = jsonEncoderOf[Env, Throwable]

But it did not solve a problem.


Solution

  • It is not possible to encode automatically a Java Hierarchy with Circe (or any other library) (I am pretty sure of this).

    So you have 3 possibilities:

    1. Just use the Message of the error:

      case GET -> Root / "things"  =>
          things.all.foldM (
            error => InternalServerError(error.getMessage()),
            Ok(_)
          )
      
    2. Or get rid of the Throwable:

        sealed trait MyError
        final case class SecondError(msg: String) extends MyError
      

      And now you can encode the error

      ...
      case GET -> Root / "things"  =>
        things.all.foldM (
          error => InternalServerError(error),
          Ok(_)
        )
      
    3. Map your Throwable to your own Error (Sealed Trait without Throwable):

      ...
      case GET -> Root / "things"  =>
        things.all
          .mapError{
            case ex: IllegalArgumentException => SecondError(ex.getMessage)
            case ex => FirstError(ex.getMessage)
         }
          .foldM (
          error => InternalServerError(error),
          Ok(_)
        )