yegor256/factbase

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

Open

#670 opened on Jul 7, 2026

View on GitHub
 (1 comment) (0 reactions) (0 assignees)Ruby (17 forks)github user discovery
bughelp wanted

Repository metrics

Stars
 (19 stars)
PR merge metrics
 (PR metrics pending)

Description

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.

Contributor guide