---
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>
