yegor256/factbase

`(div ...)` term crashes with raw `ZeroDivisionError` when the divisor is zero

Open

#670 创建于 2026年7月7日

在 GitHub 查看
 (1 评论) (0 反应) (0 负责人)Ruby (17 fork)github user discovery
bughelp wanted

仓库指标

Star
 (19 star)
PR 合并指标
 (PR 指标待抓取)

描述

What happens

A query that uses the (div a b) term where the second operand evaluates to the integer 0 crashes with a raw ZeroDivisionError that leaks internal implementation details to the caller.

Factbase::Arithmetic#evaluate (used by Factbase::Div) finishes with:

# lib/factbase/terms/arithmetic.rb:53
v.send(@op, r)

For div, @op is :/. When r is an integer 0, Integer#/ raises ZeroDivisionError, which the term does not handle. Factbase::Term#evaluate then re-wraps it, embedding the raw "divided by 0" text together with internal file paths and line numbers.

Reproduced locally against the current master:

fb = Factbase.new
f = fb.insert
f.a = 10
f.b = 0
fb.query('(eq 1 (div a b))').each.to_a

Result:

RuntimeError: "\"divided by 0\" at (div a b) at .../lib/factbase/terms/arithmetic.rb:53:in 'Integer#/'"
  at (eq 1 (div a b)) at .../lib/factbase/term.rb:212:in 'Factbase::Term#evaluate'

A non-zero divisor works correctly ((div 8 2) matches as expected). Note also the inconsistency: a Float zero divisor (0.0) yields Infinity with no error, while an Integer 0 crashes — the same query can succeed or blow up depending only on the numeric type of the divisor.

This is reachable in real pipelines: any (div ...) computing a ratio or average (success rates, per-item averages, etc.) hits it whenever the denominator is legitimately 0 — e.g. before any data has accumulated — and takes down the judge with a stack-leaking error rather than a clean failure.

What should happen

Factbase::Arithmetic should detect a zero divisor for the div operation and raise a clean, domain-level error (for example Cannot divide by zero in (div ...)), consistent with how other terms report bad input, instead of letting a raw ZeroDivisionError with internal paths and line numbers escape through Term#evaluate. The Integer and Float zero-divisor paths should also behave consistently.

贡献者指南