Integer modulo (%) by a zero divisor errors with `floating-point exception` (22P01) instead of `division by zero`
- Dominant language
- C
- Stars
- 4.8k
- Forks
- 523
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 9
Description
## Bug description
Computing an integer modulo `%` whose divisor is zero makes AGE 1.8.0 fail with a misclassified error: `ERROR: 22P01: floating-point exception`, whose detail text only *guesses* that division by zero is involved. The same zero divisor through the sibling division operator `/` correctly raises `division by zero` (22012), and so does native PostgreSQL `SELECT 5 % 0`. The `%` path is the only one that leaks a low-level hardware signal (SIGFPE from integer division by zero) instead of reporting a proper arithmetic error.
Root cause: in `src/backend/utils/adt/agtype_ops.c`, `agtype_mod` computes `lhs % rhs` for integer operands with **no zero-divisor guard**, whereas the sibling `agtype_div` explicitly checks `rhs == 0` and raises `ERRCODE_DIVISION_BY_ZERO`. An unprotected `int % 0` traps as SIGFPE, which PostgreSQL's signal handler surfaces as `ERRCODE_FLOATING_POINT_EXCEPTION`.
No graph data is required — a bare `RETURN 5 % 0` (no `MATCH`) is enough to trigger it.
## Access method
- Command line via `psql`, inside the official Docker container `apache/age:1.8.0`
## Data setup
No data is required — the error reproduces on an empty graph. Only the graph itself must exist:
```pgsql
CREATE EXTENSION IF NOT EXISTS age;
LOAD 'age';
SET search_path = ag_catalog, "$user", public;
SELECT create_graph('graph_test');
```
## Command that triggers the error
```pgsql
SELECT * FROM cypher('graph_test', $$ RETURN 5 % 0 $$) AS (c0 agtype);
```
```
ERROR: 22P01: floating-point exception
DETAIL: An invalid floating-point operation was signaled. This probably means an out-of-range result or an invalid operation, such as division by zero.
```
The zero divisor can be a literal (`0`), a property value (`CREATE (n {q: 0})` then `MATCH (n) WHERE (n.q) % 0 = 0`), or a bound variable — all raise the same error.
The same division by zero behaves correctly in every other path, all run in the same session:
- `RETURN 5 / 0` → `ERROR: division by zero` (the `/` operator guards `rhs == 0`)
- Native PostgreSQL `SELECT 5 % 0;` → `ERROR: division by zero`
- Non-zero divisor `RETURN 5 % 2` → returns `1`
## Expected behavior
Modulo by zero *is* division by zero. `RETURN 5 % 0` should raise the same clean `division by zero` (22012) that the `/` operator and native PostgreSQL raise, not an unrelated `floating-point exception`. The error should come from a deliberate zero-divisor check, not from an unhandled hardware signal.
## Environment
- Version: 1.8.0 (official `apache/age:1.8.0` Docker image)
- PostgreSQL: 18.1 (Debian 18.1-1.pgdg13+2), x86_64
Contributor guide
Research direction
Start in src/backend/utils/adt/agtype_ops.c, inspect agtype_mod alongside agtype_div and reproduce the issue with the provided psql cypher command. Add the missing zero-divisor handling for integer modulo, then verify that RETURN 5 % 0 reports division by zero (22012) while RETURN 5 % 2 still returns 1.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, postgresql
- Domain
- backend, database
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 86/100