apache / apache/age

Integer modulo (%) by a zero divisor errors with `floating-point exception` (22P01) instead of `division by zero`

Open Beginner friendly
#2,514 3 comments 0 reactions 0 assignees View on GitHub
bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.