BUG #19823: JSON_VALUE(... RETURNING jsonb) silently returns NULL for PASSING values of NaN / Infinity; the expo

From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: 303677365(at)qq(dot)com
Subject: BUG #19823: JSON_VALUE(... RETURNING jsonb) silently returns NULL for PASSING values of NaN / Infinity; the expo
Date: 2026-11-01 08:06:12
Message-ID: 19823-17cb42c43b9ee661@postgresql.org
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

The following bug has been logged on the website:

Bug reference: 19823
Logged by: chunling qin
Email address: 303677365(at)qq(dot)com
PostgreSQL version: 18.6
Operating system: Linux (TencentOS 4.4, x86_64)
Description:

Hello,

When a PASSING variable holds a numeric NaN or Infinity, JSON_VALUE with
RETURNING jsonb silently returns NULL. With ERROR ON ERROR the swallowed
error surfaces, and it points at JSON parsing rather than at the numeric
encoding that actually failed:

SELECT JSON_VALUE(jsonb '{}', '$x'
PASSING 'NaN'::numeric AS x RETURNING jsonb) AS nan_default;
-- actual: (NULL) expected: "NaN", like every other path below

SELECT JSON_VALUE(jsonb '{}', '$x'
PASSING 'Infinity'::float8 AS x RETURNING jsonb) AS inf_default;
-- actual: (NULL)

-- adding ERROR ON ERROR exposes what was swallowed:
SELECT JSON_VALUE(jsonb '{}', '$x'
PASSING 'NaN'::numeric AS x RETURNING jsonb ERROR ON ERROR);
-- ERROR: 22P02: invalid input syntax for type json
-- DETAIL: Token "NaN" is invalid.
-- CONTEXT: JSON data, line 1: NaN

The same value survives on every other path, so only the jsonb-encoding
route of JSON_VALUE drops it:

RETURNING numeric / text / float8 -> NaN / Infinity (kept)
JSON_QUERY(..., RETURNING jsonb) same args -> NaN (kept)
JSON_TABLE(... COLUMNS (j jsonb ...)) -> NaN, jsonb_typeof =
number
to_jsonb('NaN'::numeric) -> "NaN" (kept)

Expected: the jsonb rendering of a PASSING variable should agree with
to_jsonb() / JSON_QUERY() / JSON_TABLE() (which encode NaN as the string
"NaN"); at minimum, if the value cannot be encoded, the error raised
under ERROR ON ERROR should be attributed to the numeric encoding step,
not reported as a JSON parse error.

Actual: the field silently disappears from the output (NULL), and the
error message, when forced out, misattributes the cause.

For context, this is the same family as the timestamptz PASSING rendering
difference (same jsonb-encoding route of PASSING values), but the
mechanism is distinct and the impact is silent data loss: any row whose
sensor/financial value is NaN or Infinity loses that field in the JSON
output, with no warning, and downstream consumers cannot tell "no data"
apart from "bad data".

Reproduced on:
- PostgreSQL 18.6 (REL_18_STABLE, self-built, snapshot 2026-10-26)
- PostgreSQL 20devel (snapshot of 2026-10-29)

A draft fix location would be the numeric branch of the PASSING-to-jsonb
item encoding (the caller of json_errsave_error, jsonfuncs.c:662):
encode non-finite numerics the way to_jsonb() does.

Regards,
Chunling Qin

Browse pgsql-bugs by date

  From Date Subject
Next Message PG Bug reporting form 2026-11-01 08:07:24 BUG #19824: OMIT QUOTES breaks non-string results: array / composite / array-domain coercions in JSON_QUERY / JS
Previous Message Michael Paquier 2026-11-01 08:00:31 Re: BUG #19795: pgoutput: walsender crashes on START_REPLICATION option without a value