public static Throwable getRootCause(Throwable throwable) {
    if (throwable == null) {
      return null;
    }
    Throwable rootCause = throwable;
    // this is to avoid infinite loops for recursive cases
    final Set<Throwable> seenThrowables = new HashSet<>();
    seenThrowables.add(rootCause);
    while ((rootCause.getCause() != null && !seenThrowables.contains(rootCause.getCause()))) {
      seenThrowables.add(rootCause.getCause());
      rootCause = rootCause.getCause();
    }
    return rootCause;
  }
Introspects the {@link Throwable} to obtain the root cause.

<p>This method walks through the exception chain to the last element, "root" of the tree, using
{@link Throwable#getCause()}, and returns that exception.

@param throwable the throwable to get the root cause for, may be null
@return the root cause of the {@link Throwable}, {@code null} if null throwable input
core/src/main/java/feign/utils/ExceptionUtils.java