📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

适用版本: 6.8-8.11

1. 错误异常的基本描述 #

failed to find low and high distance values 表示 Elasticsearch 在解析模糊查询(fuzziness)的 AUTO 模式自定义阈值时,无法从传入的字符串中提取出合法的 lowhigh 两个整数值。该异常属于 parse_exception,通常在查询 DSL 解析阶段抛出,请求尚未真正执行就会被拒绝。

常见现象 #

  • 查询请求返回 400 Bad Request,响应体中包含 failed to find low and high distance values 错误信息。
  • 使用 AUTO 格式设置模糊度时,无论查询本身是否合理,只要 fuzziness 参数格式不正确就会直接报错。
  • 在应用日志或 Elasticsearch 服务端日志中可以看到 ElasticsearchParseExceptionNumberFormatException 相关的异常栈。
  • 如果是通过模板、前端表单或动态拼接生成 fuzziness 值,问题往往集中出现在特定输入条件下,表现为间歇性失败。

典型报错与异常栈 #

ElasticsearchParseException: failed to parse [AUTO:3] as "auto:int,int"
Caused by: java.lang.NumberFormatException: For input string: ""
    at org.elasticsearch.common.lucene.search.fuzziness.Fuzziness.parse(AUTO:3)

2. 为什么会发生这个错误 #

fuzziness 参数支持以下格式:

格式说明
012固定编辑距离
AUTO默认阈值(low=3, high=6)
AUTO:low,high自定义阈值,如 AUTO:2,5
AUTO:low,high,max_expansions自定义阈值及最大扩展数(部分版本支持)

当使用 AUTO:low,high 格式时,Elasticsearch 会按冒号和逗号分割字符串,并期望得到两个整数。如果分割后无法得到恰好两个整数,就会抛出 failed to find low and high distance values

常见原因包括:

  • 格式不完整:只写了 AUTO:3,缺少 high 值,冒号后只有一个数字。
  • 分隔符错误:使用了分号 ;、空格、中文逗号 或全角字符,而不是英文逗号 ,
  • 阈值非整数lowhigh 位置为空字符串、包含字母或其他非法字符,无法解析为 int
  • 拼接逻辑缺陷:业务代码动态拼接 fuzziness 值时,变量为空或类型错误,生成了 AUTO:AUTO:null,6 等非法字符串。
  • 模板渲染残留:模板语言中变量未正常替换,最终传入了 AUTO:{{low}},{{high}} 这类原始占位符文本。

3. 如何排查和解决这个异常 #

建议按以下步骤定位问题:

  1. 抓取完整请求 DSL:从应用日志或 Elasticsearch 慢查询日志中获取最终发送到 Elasticsearch 的查询体,重点检查 fuzziness 字段的实际值。
  2. 确认 fuzziness 格式:如果使用 AUTO 自定义阈值,确保格式严格为 AUTO:low,high,即冒号后紧跟两个整数,中间用英文逗号分隔。
  3. 检查拼接来源:如果 fuzziness 值来自前端输入、配置文件或模板渲染,回溯生成逻辑,确认变量是否可能为空或类型错误。
  4. 简化复现:先用标准 AUTO 或固定整数(如 2)替换当前值,验证查询本身是否合法,排除其他参数干扰。
  5. 查看日志上下文:结合 Elasticsearch 服务端日志中的异常栈,确认是在解析哪个字段、哪段字符串时失败。

排查时需要注意的问题 #

  • 不要只看 fuzziness 的默认值,要检查所有动态赋值路径,包括默认值和覆盖逻辑。
  • 如果项目中使用了多个搜索入口(如搜索接口、建议接口、补全接口),需要逐一确认各入口的 fuzziness 构造方式是否一致。
  • 注意 AUTO 格式在 Elasticsearch 不同版本中的细微差异,低版本不支持 AUTO:low,high,max_expansions 形式。

4. 如何解决这个错误 #

常用修复思路 #

  • 修正格式:将不完整的 AUTO:3 改为完整格式 AUTO:3,6,或直接改用标准 AUTO
  • 统一分隔符:确保使用英文冒号 : 和英文逗号 ,,避免使用全角符号或空格。
  • 增加参数校验:在业务代码中为 fuzziness 参数增加格式校验,非法值直接拒绝或给出明确报错,避免把脏数据传给 Elasticsearch。
  • 兜底默认值:当 lowhigh 变量为空时,使用合理的默认值(如 AUTO:3,6)而非拼接出半截字符串。
  • 模板占位符清理:如果使用模板引擎,确保占位符在渲染后有合法的 fallback 值。

修复示例 #

{
  "query": {
    "match": {
      "title": {
        "query": "elasticsearch",
        "fuzziness": "AUTO:2,5"
      }
    }
  }
}
// Java 示例:安全地构造 fuzziness 值
int low = getLowThreshold();   // 可能为 null 或 0
int high = getHighThreshold();

String fuzziness;
if (low > 0 && high > 0) {
    fuzziness = "AUTO:" + low + "," + high;
} else {
    fuzziness = "AUTO"; // 兜底为默认阈值
}

借助 INFINI 产品提升排障效率 #

  • INFINI Console 可以查看查询请求详情、DSL 内容和错误趋势,帮助快速定位是哪一类查询在产生格式错误。
  • INFINI Gateway 可以部署在 Elasticsearch 前面,对请求做校验、改写和审计,在非法 fuzziness 值到达后端之前进行拦截和修正。

5. 小结 #

failed to find low and high distance values 本质上是 fuzziness 参数格式错误,核心原因是 AUTO:low,high 字符串没有严格按照 冒号 + 两个整数 + 逗号 的格式提供。排查时优先确认最终发送到 Elasticsearch 的 DSL 中 fuzziness 的实际值,修复时重点做好参数校验和兜底处理,避免把不完整的字符串直接传给搜索引擎。

相关错误 #

附:日志上下文 #

下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题:

try {
    // 解析 AUTO:low,high 格式
    String[] parts = fuzzinessString.split("[:]")[1].split("[,]");
    int low = Integer.parseInt(parts[0]);
    int high = Integer.parseInt(parts[1]);
    return Fuzziness.buildAUTO(low, high);
} catch (NumberFormatException e) {
    throw new ElasticsearchParseException(
        "failed to parse [{}] as \"auto:int,int\"", e, fuzzinessString);
}