blob: 091405cb960560713cb90a3f7a60760839ffb639 [file] [view]
---
layout: global
title: Error Message Guidelines
type: "page"
navigation:
weight: 5
show: true
---
This guide is a reference for composing standardized and actionable
error messages in Apache Spark.
### Include What, Why, and How
Exceptions thrown from Spark should answer the Five W's and How:
- **Who** encountered the problem?
- **What** was the problem?
- **When** did the problem happen?
- **Where** did the problem happen?
- **Why** did the problem happen?
- **How** can the problem be solved?
The context provided by exceptions can help answer **who** (usually the
user), **when** (usually included in the log via <code>log4j</code>), and **where**
(usually included in the stack trace). However, these answers alone are
often insufficient for the user to solve the problem. An error message
that answers the remaining questions
--- **what**, **why**, and **how** --- minimizes user frustration.
#### Explicitly answer What, Why and How
In many cases, the error message should explicitly answer **what**,
**why**, and **how**.
##### Example 1
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/569fb133d09e24e4ed56ed7efff641512d98b01b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala#L160">
Unable to generate an encoder for inner class {} without access to the
scope that this class was defined in. Try moving this class out of its
parent class.
</a>
</code>
- **What:** Unable to generate encoder inner class.
- **Why:** Did not have access to the scope that the class was defined in.
- **How:** Try moving this class out of its parent class.
##### Example 2
If the proposed fix (**how**) feels arbitrary, providing an explanation
for **why** the error occurred can reduce user frustration.
**Before**
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/03dd33cc982ebb3de4354274ac49da31521b8195/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala#L498">
<span style="background-color: #ffcccc">Unsupported</span> function name {}.
</a>
</code>
- **What:** Unsupported function name.
- **Why:** Unclear.
- **How:** Unclear.
**After**
*Function name {} <span style="background-color: #ccffcc">is invalid. Temporary functions cannot belong to a
catalog. Specify a function name with one or two parts.</span>*
- **What:** Invalid function name.
- **Why:** Temporary functions cannot belong to a catalog.
- **How:** Specify a function name with one or two parts.
#### Implicitly answer How
Not all error messages should be this verbose. Sometimes, explicitly
explaining **how** to resolve the problem would be redundant;
you may skip an explicit explanation in this case.
##### Example 1
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/e5d972e84e973d9a2e62312dc471df30c35269bc/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala#L63">
Invalid pivot column {}. Pivot columns must be comparable.
</a>
</code>
- **What:** Invalid pivot column.
- **Why:** Pivot columns must be comparable.
- **How (*****implied by Why*****):** Use comparable pivot columns.
##### Example 2
**Before**
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/9809a2f1c5187205c81542dbdc84b71db535f6e1/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala#L325">
Cannot specify window frame for {} function
</a>
</code>
- **What:** Cannot specify window frame for the function.
- **Why**: Unclear.
- **How:** Unclear.
**After**
<code style="white-space:normal">
Cannot specify frame for window expression {}. <span style="background-color: #ccffcc">Window expression
contains mismatch between function frame {} and specification frame {}.</span>
</code>
- **What:** Cannot specify the frame for the window expression.
- **Why:** Window expression contains mismatch between function frame
and specification frame.
- **How (*****implied by Why*****):** Match the function frame and
specification frame.
##### Example 3
**Before**
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/aff6c0febb40d9713895ba00d8c77ba00f04bd16/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala#L93">
Cannot parse any decimal.
</a>
</code>
- **What:** Cannot parse decimal.
- **Why**: Unclear.
- **How:** Unclear.
**After**
<code style="white-space:normal">
Invalid decimal {}; <span style="background-color: #ccffcc">encountered error while parsing at position {}.</span>
</code>
- **What:** Invalid decimal.
- **Why**: The decimal parser encountered an error at the specified position.
- **How (*****implied by Why*****):** Fix the error at the specified position.
#### Implicitly answer Why and How
Sometimes, even explicitly explaining **why** the problem happened would
be redundant; you may skip an explicit explanation in this case.
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/569fb133d09e24e4ed56ed7efff641512d98b01b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala#L770">
Path does not exist: {}
</a>
</code>
- **What:** Path does not exist.
- **Why (*****implied by What*****):** User specified an invalid path.
- **How (*****implied by What*****):** Use a different path.
### Use clear language
#### Diction guide
<table class="table table-hover">
<thead>
<tr>
<th scope="col">Phrases</th>
<th scope="col">When to use</th>
<th scope="col">Example</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Unsupported</th>
<td>
The user may reasonably assume that the operation is supported, but it is not. This error may go away in the future if developers add support for the operation.
</td>
<td>
<code style="white-space:normal">
Data type {} is <span style="background-color: #ccffff">unsupported</span>.
</code>
</td>
</tr>
<tr>
<th rowspan="3" scope="rowgroup">
Invalid / Not allowed / Unexpected
</th>
<td rowspan="3">
The user made a mistake when specifying an operation. The message should inform the user of how to resolve the error.
</td>
<td>
<code style="white-space:normal">
Array has size {}, index {} is <span style="background-color: #ccffff">invalid</span>.
</code>
</td>
</tr>
<tr>
<td>
<code style="white-space:normal">
Found {} generators for the clause {}. Only one generator is <span style="background-color: #ccffff">allowed</span>.
</code>
</td>
</tr>
<tr>
<td>
<code style="white-space:normal">
Found an <span style="background-color: #ccffff">unexpected</span> state format version {}. Expected versions 1 or 2.
</code>
</td>
</tr>
<tr>
<th scope="row">Failed to</th>
<td>
The system encountered an unexpected error that cannot be reasonably attributed to user error.
</td>
<td>
<code style="white-space:normal">
<span style="background-color: #ccffff">Failed to</span> compile {}.
</code>
</td>
</tr>
<tr>
<th scope="row">Cannot</th>
<td>
Any time, preferably only if one of the above alternatives does not apply.
</td>
<td>
<code style="white-space:normal">
<span style="background-color: #ccffff">Cannot</span> generate code for unsupported type {}.
</code>
</td>
</tr>
</tbody>
</table>
#### Wording guide
<table class="table table-hover">
<thead>
<tr>
<th scope="col">Best practice</th>
<th scope="col">Before</th>
<th scope="col">After</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">
Use active voice
</th>
<td>
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/73857cdd87757d2888bd92f6b7c2fad709701484/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala#L704">
DataType {} is <span style="background-color: #ffcccc">not supported by</span> {}.
</a>
</code>
</td>
<td>
<code style="white-space:normal">
{} <span style="background-color: #ccffcc">does not</span> support datatype {}.
</code>
</td>
</tr>
<tr>
<th rowspan="2" scope="rowgroup">
Avoid time-based statements, such as promises of future support
</th>
<td>
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/27bec91bc971b393bd91f2ec8c6483b33f844f12/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala#L185">
Pandas UDF aggregate expressions are <span style="background-color: #ffcccc">currently</span> not supported in pivot.
</a>
</code>
</td>
<td>
<code style="white-space:normal">
Pivot <span style="background-color: #ccffcc">does not</span> support Pandas UDF aggregate expressions.
</code>
</td>
</tr>
<tr>
<td>
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/569fb133d09e24e4ed56ed7efff641512d98b01b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala#L1076">
Parquet type not <span style="background-color: #ffcccc">yet</span> supported: {}.
</a>
</code>
</td>
<td>
<code style="white-space:normal">
{} <span style="background-color: #ccffcc">does not</span> support Parquet type.
</code>
</td>
</tr>
<tr>
<th rowspan="2" scope="rowgroup">Use the present tense to describe the error and provide suggestions</th>
<td>
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/9809a2f1c5187205c81542dbdc84b71db535f6e1/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala#L166">
<span style="background-color: #ffcccc">Couldn't</span> find the reference column for {} at {}.
</a>
</code>
</td>
<td>
<code style="white-space:normal"><span style="background-color: #ccffcc">Cannot</span> find the reference column for {} at {}.</code>
</td>
</tr>
<tr>
<td>
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/9809a2f1c5187205c81542dbdc84b71db535f6e1/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala#L409">
Join strategy hint parameter <span style="background-color: #ffcccc">should be</span> an identifier or string but was {}.
</a>
</code>
</td>
<td>
<code style="white-space:normal">
Cannot use join strategy hint parameter {}. <span style="background-color: #ccffcc">Use</span> a table name or identifier to specify the parameter.
</code>
</td>
</tr>
<tr>
<th scope="row">Provide concrete examples if the resolution is unclear</th>
<td>
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/569fb133d09e24e4ed56ed7efff641512d98b01b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala#L422">
{} Hint expects a partition number as a parameter.
</a>
</code>
</td>
<td>
<code style="white-space:normal">
{} Hint expects a partition number as a parameter. <span style="background-color: #ccffcc">For example, specify 3 partitions with {}(3)</span>.
</code>
</td>
</tr>
<tr>
<th scope="row">Avoid sounding accusatory, judgmental, or insulting</th>
<td>
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/569fb133d09e24e4ed56ed7efff641512d98b01b/core/src/main/scala/org/apache/spark/resource/ResourceUtils.scala#L143">
<span style="background-color: #ffcccc">You must</span> specify an amount for {}.
</a>
</code>
</td>
<td>
<code style="white-space:normal">
{} cannot be empty. Specify an amount for {}.
</code>
</td>
</tr>
<tr>
<th scope="row">Be direct</th>
<td>
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/4b5fc1da752ec008468ef80a5717c8beab468387/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala#L119">
LEGACY store assignment policy is disallowed in Spark data source V2. <span style="background-color: #ffcccc">Please</span> set the configuration spark.sql.storeAssignmentPolicy to <span style="background-color: #ffcccc">other values</span>.
</a>
</code>
</td>
<td>
<code style="white-space:normal">
Spark data source V2 does not allow the LEGACY store assignment policy. Set the configuration spark.sql.storeAssignment to ANSI or STRICT.
</code>
</td>
</tr>
<tr>
<th scope="row">Do not use programming jargon in user-facing errors</th>
<td>
<code style="white-space:normal">
<a href="https://github.com/apache/spark/blob/4b5fc1da752ec008468ef80a5717c8beab468387/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala#L583">
RENAME TABLE source and destination databases do not match: '{}' <span style="background-color: #ffcccc">!=</span> '{}'.
</a>
</code>
</td>
<td>
<code style="white-space:normal">
RENAME TABLE source and destination databases do not match. The source database is {}, but the destination database is {}.
</code>
</td>
</tr>
</tbody>
</table>