Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

beautifyErrors middleware bug: Defining a 409 Response with a body leads to a java.util.NoSuchElementException: None.get exception #2295

Open
guizmaii opened this issue Jul 14, 2023 · 3 comments
Labels
💎 Bounty bug Something isn't working

Comments

@guizmaii
Copy link
Member

guizmaii commented Jul 14, 2023

Hey 🙂

I have an API defined this way:

val api: HttpApp[Any, Throwable] = ...

and a handler for the errors:

final case class PublicError(title: String, details: Option[String])
object PublicError {
  implicit val encoder: JsonEncoder[PublicError] = DeriveJsonEncoder.gen[PublicError]

  def from(e: DuplicateError): PublicError = ...
}

def toPublicError(e: Throwable): UIO[Response] = 
  e match {
    case e: DuplicateError => ZIO.succeed(Response(status = Status.Conflict, body = Body.fromString(PublicError.from(e).toJson)))
    ...
  }

so that in my main object, I have:

object Main extends zio.App {
  val app: App[Any] = api.mapErrorZIO(toPublicError)

  override def run = Server.serve(app)
}

When I send a request to this api, I receive a 500 Server Error instead of the 409 Conflict because this piece of code in zio-http fails with a java.util.NoSuchElementException: None.get exception:

package zio.http.internal.middlewares

private[zio] trait HtmlErrorResponses {
  ...
  
  private def formatCause(response: Response): String =
    response.httpError.get.foldCause("") { throwable =>
      s"${scala.Console.BOLD}Cause: ${scala.Console.RESET}\n ${prettify(throwable)}"
    }
    
  ...
}

It doesn't seem that we're able to define an error response with a body in zio-http.
The only function I see to define an error response is Response.fromHttpError(HttpError.Conflict) but it doesn't allow us to pass a body while the ErrorResponse type does take a body:

package zio.http

object Response {
  ...
  
  private[zio] class ErrorResponse(val body: Body, val headers: Headers, val httpError0: HttpError, val status: Status)
      extends Response 
      
  ...
}

Am I missing something?
Shouldn't we be able to define any response type with the Response.apply constructor? 🤔


Edit:
After futher investigation, it seems that this issue comes from the beautifyErrors middleware.
When I remove it, my API is correctly answering 409 Conflict

@guizmaii guizmaii added the bug Something isn't working label Jul 14, 2023
@guizmaii guizmaii changed the title Defining a 409 Response with a body leads to a java.util.NoSuchElementException: None.get exception beautifyErrors middleware bug: Defining a 409 Response with a body leads to a java.util.NoSuchElementException: None.get exception Jul 14, 2023
@jdegoes
Copy link
Member

jdegoes commented Jul 27, 2023

/bounty $75

@algora-pbc
Copy link

algora-pbc bot commented Jul 27, 2023

💎 $75 bounty • ZIO

Steps to solve:

  1. Start working: Comment /attempt #2295 with your implementation plan
  2. Submit work: Create a pull request including /claim #2295 in the PR body to claim the bounty
  3. Receive payment: 100% of the bounty is received 2-5 days post-reward. Make sure you are eligible for payouts

Thank you for contributing to zio/zio-http!

Add a bountyShare on socials

@guersam
Copy link
Contributor

guersam commented Aug 5, 2023

The piece of code calling unsafe Response#httpError.get is gone. Also, there is no Response#httpError anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💎 Bounty bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants