@@ -83,6 +83,13 @@ case class FetchFailed(
8383 * :: DeveloperApi ::
8484 * Task failed due to a runtime exception. This is the most common failure case and also captures
8585 * user program exceptions.
86+ *
87+ * `stackTrace` contains the stack trace of the exception itself. It still exists for backward
88+ * compatibility. It's better that using `this(e: Throwable, metrics: Option[TaskMetrics])` to
89+ * create `ExceptionFailure` as it will handle the backward compatibility properly.
90+ *
91+ * `fullStackTrace` is a better representation of the stack trace because it contains the whole
92+ * stack trace including the exception and its causes
8693 */
8794@ DeveloperApi
8895case class ExceptionFailure (
@@ -101,10 +108,23 @@ case class ExceptionFailure(
101108 if (fullStackTrace == null ) {
102109 // fullStackTrace is added in 1.2.0
103110 // If fullStackTrace is null, use the old error string for backward compatibility
104- Utils . exceptionString(className, description, stackTrace)
111+ exceptionString(className, description, stackTrace)
105112 } else {
106113 fullStackTrace
107114 }
115+
116+ /**
117+ * Return a nice string representation of the exception, including the stack trace.
118+ * Note: It does not include the exception's causes, and is only used for backward compatibility.
119+ */
120+ private def exceptionString (
121+ className : String ,
122+ description : String ,
123+ stackTrace : Array [StackTraceElement ]): String = {
124+ val desc = if (description == null ) " " else description
125+ val st = if (stackTrace == null ) " " else stackTrace.map(" " + _).mkString(" \n " )
126+ s " $className: $desc\n $st"
127+ }
108128}
109129
110130/**
0 commit comments