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

imapError message not returned when type decoded inside an Option #299

Open
jensraaby opened this issue Mar 17, 2021 · 2 comments
Open

imapError message not returned when type decoded inside an Option #299

jensraaby opened this issue Mar 17, 2021 · 2 comments
Labels
enhancement New feature or request

Comments

@jensraaby
Copy link

We have some codecs which bootstrap the String codec and convert values to our own internal enumeratum values.
The schema models the data as string or null, which we attempt to model as Option[OurEnumType].

The decoding works fine, except when an unexpected String comes through. The error message presented is
Exhausted alternatives for type org.apache.avro.util.Utf8 - rather than the underlying failure with our custom message.

Broadly our codec looks a bit like the following:

case class MyThing(value: String)
object MyThing {
  def fromString(s: String): Option[MyThing] = if (s=="thing") Some(MyThing(s)) else None
  implicit val codec: Codec[MyThing] =
    Codec.string.imapError(str => fromString(str).toRight(AvroError(s"$str is not what we want")))(_.value)
}

Is there a way to make the underlying error message bubble up? This issue led to a bit of head scratching because the stack trace didn't identify where the problem was either.

@jensraaby
Copy link
Author

I managed to get something which emits the correct error message with the following, but it would be nice to have something in the API to support this, similar to how Circe works

implicit val myThingCodec: Codec[Option[MyThing]] =
Codec
  .option[String]
  .imapError[Option[MyThing]] ({
    case Some(str) => fromString(str).map(Some(_)).toRight(AvroError(s"$str not what we want"))
    case None => Right(None)
  })(maybeMyThing => maybeMyThing.map(myThing => myThing.value))

@bplommer bplommer added the enhancement New feature or request label Mar 28, 2021
@bplommer
Copy link
Member

This is really a special case of a more general issue, which is that union decoders don't propagate specific errors when all alternatives fail. It could be nice to expose the reason why each alternative failed.

That said, even if we don't do that it might also be worth special-casing the Option codec so that it reports the underlying error when failing to decode a non-null value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Development

No branches or pull requests

2 participants