static Throwable unpack(final Throwable maybeRich, final Function<Component, String> serializer) {
    if (!(maybeRich instanceof ComponentMessageThrowable)) return maybeRich; // TODO: do we need to unwrap any nested exceptions?

    final @Nullable Component message = ((ComponentMessageThrowable) maybeRich).componentMessage();
    final Throwable cause = maybeRich.getCause() != null ? unpack(maybeRich.getCause(), serializer) : null;
    final Throwable[] suppressed = maybeRich.getSuppressed();

    final UnpackedComponentThrowable ret = new UnpackedComponentThrowable(maybeRich.getClass(), serializer.apply(message), cause);
    ret.setStackTrace(maybeRich.getStackTrace());
    if (suppressed.length > 0) {
      for (int i = 0; i < suppressed.length; i++) {
        ret.addSuppressed(unpack(suppressed[i], serializer));
      }
    }

    return ret;
  }
A wrapper for exceptions that implement ComponentMessageThrowable.
text-logger-slf4j/src/main/java/net/kyori/adventure/text/logger/slf4j/UnpackedComponentThrowable.java