subprojects/parseq/src/main/java/com/linkedin/parseq/BaseTask.java
private void appendTaskStackTrace(final Throwable error) {
    StackTraceElement[] taskStackTrace = _taskStackTraceHolder != null ? _taskStackTraceHolder.getStackTrace() : null;

    // At a minimum, any stack trace should have at least 3 stack frames (caller + BaseTask + getStackTrace).
    // So if there are less than 3 stack frames available then there's something fishy and it's better to ignore them.
    if (!ParSeqGlobalConfiguration.isCrossThreadStackTracesEnabled() || error == null ||
        taskStackTrace == null || taskStackTrace.length <= 2) {
      return;
    }

    StackTraceElement[] errorStackTrace = error.getStackTrace();
    if (errorStackTrace.length <= 2) {
      return;
    }

    // Skip stack frames up to the BaseTask (useless java.util.concurrent stuff)
    int skipErrorFrames = 1;
    while (skipErrorFrames < errorStackTrace.length) {
      int index = errorStackTrace.length - 1 - skipErrorFrames;
      if (!errorStackTrace[index].getClassName().equals(CANONICAL_NAME) &&
          errorStackTrace[index + 1].getClassName().equals(CANONICAL_NAME)) {
        break;
      }
      skipErrorFrames++;
    }

    // Safeguard against accidentally removing entire stack trace
    if (skipErrorFrames == errorStackTrace.length) {
      skipErrorFrames = 0;
    }

    // Skip stack frames up to the BaseTask (useless Thread.getStackTrace stuff)
    int skipTaskFrames = 1;
    while (skipTaskFrames < taskStackTrace.length) {
      if (!taskStackTrace[skipTaskFrames].getClassName().equals(CANONICAL_NAME) &&
          taskStackTrace[skipTaskFrames - 1].getClassName().equals(CANONICAL_NAME)) {
        break;
      }
      skipTaskFrames++;
    }

    // Safeguard against accidentally removing entire stack trace
    if (skipTaskFrames == taskStackTrace.length) {
      skipTaskFrames = 0;
    }

    int combinedLength = errorStackTrace.length - skipErrorFrames + taskStackTrace.length - skipTaskFrames;
    if (combinedLength <= 0) {
      return;
    }

    StackTraceElement[] concatenatedStackTrace = new StackTraceElement[combinedLength + 1];
    System.arraycopy(errorStackTrace, 0, concatenatedStackTrace,
        0, errorStackTrace.length - skipErrorFrames);
    concatenatedStackTrace[errorStackTrace.length - skipErrorFrames] =
        new StackTraceElement("********** Task \"" + getName() + "\" (above) was instantiated as following (below): **********", "",null, 0);
    System.arraycopy(taskStackTrace, skipTaskFrames, concatenatedStackTrace,
        errorStackTrace.length - skipErrorFrames + 1, taskStackTrace.length - skipTaskFrames);
    error.setStackTrace(concatenatedStackTrace);
  }
private void appendTaskStackTrace(final Throwable error) {
    StackTraceElement[] taskStackTrace = _taskStackTraceHolder != null ? _taskStackTraceHolder.getStackTrace() : null;

    // At a minimum, any stack trace should have at least 3 stack frames (caller + BaseTask + getStackTrace).
    // So if there are less than 3 stack frames available then there's something fishy and it's better to ignore them.
    if (!ParSeqGlobalConfiguration.isCrossThreadStackTracesEnabled() || error == null ||
        taskStackTrace == null || taskStackTrace.length <= 2) {
      return;
    }

    StackTraceElement[] errorStackTrace = error.getStackTrace();
    if (errorStackTrace.length <= 2) {
      return;
    }

    // Skip stack frames up to the BaseTask (useless java.util.concurrent stuff)
    int skipErrorFrames = 1;
    while (skipErrorFrames < errorStackTrace.length) {
      int index = errorStackTrace.length - 1 - skipErrorFrames;
      if (!errorStackTrace[index].getClassName().equals(CANONICAL_NAME) &&
          errorStackTrace[index + 1].getClassName().equals(CANONICAL_NAME)) {
        break;
      }
      skipErrorFrames++;
    }

    // Safeguard against accidentally removing entire stack trace
    if (skipErrorFrames == errorStackTrace.length) {
      skipErrorFrames = 0;
    }

    // Skip stack frames up to the BaseTask (useless Thread.getStackTrace stuff)
    int skipTaskFrames = 1;
    while (skipTaskFrames < taskStackTrace.length) {
      if (!taskStackTrace[skipTaskFrames].getClassName().equals(CANONICAL_NAME) &&
          taskStackTrace[skipTaskFrames - 1].getClassName().equals(CANONICAL_NAME)) {
        break;
      }
      skipTaskFrames++;
    }

    // Safeguard against accidentally removing entire stack trace
    if (skipTaskFrames == taskStackTrace.length) {
      skipTaskFrames = 0;
    }

    int combinedLength = errorStackTrace.length - skipErrorFrames + taskStackTrace.length - skipTaskFrames;
    if (combinedLength <= 0) {
      return;
    }

    StackTraceElement[] concatenatedStackTrace = new StackTraceElement[combinedLength + 1];
    System.arraycopy(errorStackTrace, 0, concatenatedStackTrace,
        0, errorStackTrace.length - skipErrorFrames);
    concatenatedStackTrace[errorStackTrace.length - skipErrorFrames] =
        new StackTraceElement("********** Task \"" + getName() + "\" (above) was instantiated as following (below): **********", "",null, 0);
    System.arraycopy(taskStackTrace, skipTaskFrames, concatenatedStackTrace,
        errorStackTrace.length - skipErrorFrames + 1, taskStackTrace.length - skipTaskFrames);
    error.setStackTrace(concatenatedStackTrace);
  }
Concatenate stack traces if kept the original stack trace from the task creation