override def asJsError: Option[JsError] = Some()

in server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/EmailSetSerializer.scala [152:266]


      override def asJsError: Option[JsError] = Some(JsError(s"Value associated with $property is invalid: $cause"))
    }

    private case class MailboxAddition(id: MailboxId) extends EntryValidation

    private case class MailboxRemoval(id: MailboxId) extends EntryValidation

    private case class MailboxReset(ids: MailboxIds) extends EntryValidation

    private case class KeywordsReset(keywords: Keywords) extends EntryValidation

    private case class KeywordAddition(keyword: Keyword) extends EntryValidation

    private case class KeywordRemoval(keyword: Keyword) extends EntryValidation

  }

  private implicit val messageIdWrites: Writes[MessageId] = messageId => JsString(messageId.serialize)
  private implicit val messageIdReads: Reads[MessageId] = {
    case JsString(serializedMessageId) => Try(JsSuccess(messageIdFactory.fromString(serializedMessageId)))
      .fold(_ => JsError("Invalid messageId"), messageId => messageId)
    case _ => JsError("Expecting messageId to be represented by a JsString")
  }

  private implicit val mailboxIdsMapReads: Reads[Map[MailboxId, Boolean]] =
    Reads.mapReads[MailboxId, Boolean] {s => Try(mailboxIdFactory.fromString(s)).fold(e => JsError(e.getMessage), JsSuccess(_)) } (mapMarkerReads)

  private implicit val mailboxIdsReads: Reads[MailboxIds] = jsValue => mailboxIdsMapReads.reads(jsValue).map(
    mailboxIdsMap => MailboxIds(mailboxIdsMap.keys.toList))

  private implicit val emailSetUpdateReads: Reads[EmailSetUpdate] = {
    case o: JsObject => EmailSetUpdateReads.reads(o)
    case _ => JsError("Expecting a JsObject to represent an EmailSetUpdate")
  }

  private implicit val updatesMapReads: Reads[Map[UnparsedMessageId, JsObject]] =
    Reads.mapReads[UnparsedMessageId, JsObject] {string => refineV[IdConstraint](string)
      .fold(e => JsError(s"messageId needs to match id constraints: $e"),
        id => JsSuccess(UnparsedMessageId(id))) }

  private implicit val createsMapReads: Reads[Map[EmailCreationId, JsObject]] =
    Reads.mapReads[EmailCreationId, JsObject] {s => refineV[IdConstraint](s)
      .fold(e => JsError(s"email creationId needs to match id constraints: $e"),
        id => JsSuccess(EmailCreationId(id))) }

  private implicit val keywordReads: Reads[Keyword] = {
    case jsString: JsString => Keyword.parse(jsString.value)
      .fold(JsError(_),
        JsSuccess(_))
    case _ => JsError("Expecting a string as a keyword")
  }

  private implicit val keywordsMapReads: Reads[Map[Keyword, Boolean]] =
    Reads.mapReads[Keyword, Boolean] {string => Keyword.parse(string).fold(JsError(_), JsSuccess(_)) } (mapMarkerReads)
  private implicit val keywordsReads: Reads[Keywords] = jsValue => keywordsMapReads.reads(jsValue).flatMap(
    keywordsMap => STRICT_KEYWORDS_FACTORY.fromSet(keywordsMap.keys.toSet)
      .fold(e => JsError(e.getMessage), keywords => JsSuccess(keywords)))

  private implicit val blobIdWrites: Writes[BlobId] = Json.valueWrites[BlobId]
  private implicit val blobIdReads: Reads[BlobId] = {
    case JsString(string) => BlobId.of(string)
      .toEither.fold(
        e => JsError(s"blobId does not match Id constraints: $e"),
        blobId => JsSuccess(blobId))
    case _ => JsError("blobId needs to be represented by a JsString")
  }
  private implicit val unparsedMessageIdWrites: Writes[UnparsedMessageId] = Json.valueWrites[UnparsedMessageId]
  private implicit val unparsedMessageIdReads: Reads[UnparsedMessageId] = {
    case JsString(string) => refined.refineV[IdConstraint](string)
      .fold(
        e => JsError(s"messageId does not match Id constraints: $e"),
        id => JsSuccess(UnparsedMessageId(id)))
    case _ => JsError("messageId needs to be represented by a JsString")
  }
  private implicit val unitWrites: Writes[Unit] = _ => JsNull
  private implicit val updatedWrites: Writes[Map[MessageId, Unit]] = mapWrites[MessageId, Unit](_.serialize, unitWrites)
  private implicit val notDestroyedWrites: Writes[Map[UnparsedMessageId, SetError]] = mapWrites[UnparsedMessageId, SetError](_.id.value, setErrorWrites)
  private implicit val destroyIdsReads: Reads[DestroyIds] = Json.valueFormat[DestroyIds]
  private implicit val destroyIdsWrites: Writes[DestroyIds] = Json.valueWrites[DestroyIds]
  private implicit val emailRequestSetReads: Reads[EmailSetRequest] = Json.reads[EmailSetRequest]
  private implicit val threadIdWrites: Writes[ThreadId] = Json.valueWrites[ThreadId]
  private implicit val emailCreationResponseWrites: Writes[EmailCreationResponse] = Json.writes[EmailCreationResponse]
  private implicit val createsMapWrites: Writes[Map[EmailCreationId, EmailCreationResponse]] =
    mapWrites[EmailCreationId, EmailCreationResponse](_.id.value, emailCreationResponseWrites)
  private implicit val notCreatedMapWrites: Writes[Map[EmailCreationId, SetError]] =
    mapWrites[EmailCreationId, SetError](_.id.value, setErrorWrites)

  private implicit val stateWrites: Writes[UuidState] = Json.valueWrites[UuidState]
  private implicit val emailResponseSetWrites: OWrites[EmailSetResponse] = Json.writes[EmailSetResponse]

  private implicit val subjectReads: Reads[Subject] = Json.valueReads[Subject]
  private implicit val emailerNameReads: Reads[EmailerName] = Json.valueReads[EmailerName]
  private implicit val unvalidatedEmailReads: Reads[UncheckedEmail] = Json.valueReads[UncheckedEmail]

  private implicit val headerMessageIdReads: Reads[HeaderMessageId] = Json.valueReads[HeaderMessageId]
  private implicit val emailAddressReads: Reads[EmailAddress] = Json.reads[EmailAddress]
  private implicit val unvalidatedEmailAddressReads: Reads[UncheckedEmailAddress] = Json.reads[UncheckedEmailAddress]
  private implicit val unvalidatedAddressesHeaderValueReads: Reads[UncheckedAddressesHeaderValue] = Json.valueReads[UncheckedAddressesHeaderValue]
  private implicit val addressesHeaderValueReads: Reads[AddressesHeaderValue] = Json.valueReads[AddressesHeaderValue]
  private implicit val messageIdsHeaderValueReads: Reads[MessageIdsHeaderValue] = {
    case JsArray(value) => value.map(headerMessageIdReads.reads)
      .map(_.asEither)
      .toList
      .sequence
      .fold(e => JsError(e),
        ids => JsSuccess(MessageIdsHeaderValue(Some(ids).filter(_.nonEmpty))))
    case jsValue => JsError(s"expected JsArray, got $jsValue")
  }

  private implicit val isTruncatedReads: Reads[IsTruncated] = Json.valueReads[IsTruncated]
  private implicit val isEncodingProblemReads: Reads[IsEncodingProblem] = Json.valueReads[IsEncodingProblem]
  private implicit val clientEmailBodyValueWithoutHeadersReads: Reads[ClientEmailBodyValueWithoutHeaders] = Json.reads[ClientEmailBodyValueWithoutHeaders]
  private implicit val clientEmailBodyValueReads: Reads[ClientEmailBodyValue] = {
    case o: JsObject =>
      if (o.value.contains("headers")) {