错误消息指南

本指南是关于在 Apache Spark 中编写标准化且可操作的错误消息的参考。

包含“是什么”、“为什么”和“如何”

Spark 中抛出的异常应回答五个 W 和一个 How

  • 遇到了问题?
  • 什么是问题?
  • 何时发生问题?
  • 何地发生问题?
  • 为什么发生问题?
  • 如何解决问题?

异常提供的上下文可以帮助回答(通常是用户)、何时(通常通过log4j包含在日志中)和何地(通常包含在堆栈跟踪中)。然而,仅凭这些答案通常不足以让用户解决问题。一个回答剩余问题——是什么为什么如何——的错误消息能最大程度地减少用户沮丧感。

明确回答“是什么”、“为什么”和“如何”

在许多情况下,错误消息应明确回答是什么为什么如何

示例 1

无法为内部类 {} 生成编码器,因为它无法访问定义此类的作用域。请尝试将此类移出其父类。

  • 是什么: 无法生成内部类编码器。
  • 为什么: 无法访问定义该类的作用域。
  • 如何: 尝试将此类移出其父类。
示例 2

如果建议的修复方法(如何)感觉随意,提供关于错误发生原因的解释可以减少用户沮丧感。

之前

不支持的函数名 {}。

  • 是什么: 不支持的函数名。
  • 为什么: 不明确。
  • 如何: 不明确。

之后

函数名 {} 无效。临时函数不能属于目录。请指定一个包含一个或两个部分的函数名。

  • 是什么: 无效的函数名。
  • 为什么: 临时函数不能属于目录。
  • 如何: 指定一个包含一个或两个部分的函数名。

隐含回答“如何”

并非所有错误消息都应如此冗长。有时,明确解释如何解决问题是多余的;在这种情况下,您可以跳过明确的解释。

示例 1

无效的枢轴列 {}。枢轴列必须是可比较的。

  • 是什么: 无效的枢轴列。
  • 为什么: 枢轴列必须是可比较的。
  • 如何(通过“为什么”暗示): 使用可比较的枢轴列。
示例 2

之前

不能为 {} 函数指定窗口框架

  • 是什么: 不能为函数指定窗口框架。
  • 为什么: 不明确。
  • 如何: 不明确。

之后

不能为窗口表达式 {} 指定框架。 窗口表达式中的函数框架 {} 与规范框架 {} 不匹配。

  • 是什么: 不能为窗口表达式指定框架。
  • 为什么: 窗口表达式中的函数框架与规范框架不匹配。
  • 如何(通过“为什么”暗示): 匹配函数框架和规范框架。
示例 3

之前

无法解析任何小数。

  • 是什么: 无法解析小数。
  • 为什么: 不明确。
  • 如何: 不明确。

之后

无效小数 {}; 在位置 {} 解析时遇到错误。

  • 是什么: 无效小数。
  • 为什么: 小数解析器在指定位置遇到错误。
  • 如何(通过“为什么”暗示): 修复指定位置的错误。

隐含回答“为什么”和“如何”

有时,即使明确解释问题发生原因也是多余的;在这种情况下,您可以跳过明确的解释。

路径不存在:{}

  • 是什么: 路径不存在。
  • 为什么(通过“是什么”暗示): 用户指定了无效路径。
  • 如何(通过“是什么”暗示): 使用不同的路径。

使用清晰的语言

措辞指南

短语 何时使用 示例
Unsupported (不支持的) 用户可能合理地认为该操作是受支持的,但实际上并非如此。如果开发者将来添加对该操作的支持,此错误可能会消失。 数据类型 {} 不支持
Invalid / Not allowed / Unexpected (无效的 / 不允许的 / 意外的) 用户在指定操作时犯了错误。消息应告知用户如何解决错误。 数组大小为 {},索引 {} 无效
为子句 {} 找到 {} 个生成器。只允许一个生成器。
找到一个意外的状态格式版本 {}。预期版本为 1 或 2。
Failed to (未能) 系统遇到意外错误,不能合理归因于用户错误。 未能编译 {}。
Cannot (不能) 任何时候,最好只在以上替代方案不适用时使用。 不能为不支持的类型 {} 生成代码。

用语指南

最佳实践 之前 之后
使用主动语态 数据类型 {} 不被 {} 支持 {} 不支持数据类型 {}。
避免基于时间的陈述,例如未来支持的承诺 Pandas UDF 聚合表达式目前在枢轴中不支持。 枢轴不支持Pandas UDF 聚合表达式。
Parquet 类型不支持:{}。 {} 不支持Parquet 类型。
使用现在时描述错误并提供建议 无法在 {} 找到 {} 的引用列。 不能在 {} 找到 {} 的引用列。
连接策略提示参数应该是标识符或字符串,但却是 {}。 不能使用连接策略提示参数 {}。请使用表名或标识符指定参数。
如果解决方案不明确,请提供具体示例 {} 提示期望分区号作为参数。 {} 提示期望分区号作为参数。例如,使用 {}(3) 指定 3 个分区
避免听起来有指责性、评判性或侮辱性 你必须为 {} 指定一个数量。 {} 不能为空。请为 {} 指定一个数量。
直接明了 Spark 数据源 V2 中不允许使用 LEGACY 存储分配策略。请将配置 spark.sql.storeAssignmentPolicy 设置为其他值 Spark 数据源 V2 不允许 LEGACY 存储分配策略。请将配置 spark.sql.storeAssignment 设置为 ANSI 或 STRICT。
在面向用户的错误中不要使用编程术语 RENAME TABLE 源和目标数据库不匹配:'{}' != '{}'。 RENAME TABLE 源和目标数据库不匹配。源数据库是 {},但目标数据库是 {}。
最新消息

存档