Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wyTeC-003PwN-1v for pgsql-bugs@arkaria.postgresql.org; Mon, 24 Aug 2026 12:19:28 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wyTeA-002PXG-2r for pgsql-bugs@arkaria.postgresql.org; Mon, 24 Aug 2026 12:19:26 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wyHu8-000Uh9-02 for pgsql-bugs@lists.postgresql.org; Sun, 23 Aug 2026 23:47:08 +0000 Received: from mahout.postgresql.org ([2001:4800:3e1:1::227]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1wyHu5-0000000264W-1UoW for pgsql-bugs@lists.postgresql.org; Sun, 23 Aug 2026 23:47:07 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=postgresql.org; s=20171124; h=Message-ID:Date:Reply-To:Cc:From:To:Subject: Content-Transfer-Encoding:MIME-Version:Content-Type:Sender:Content-ID: Content-Description:In-Reply-To:References; bh=Rb+hqPRhBFsC0iFSBNRcBVHOERp9ahacfNLMuj55hw4=; b=oUshZRbVPAiKWvUNmvWK8xw7oC THqNAz/iLTNJ+6MaYyutfRk0kav3psha4CvJmX0X6DXsPW9s8OMn5bBIhsXWxH8BMcA0MaBBAmQzA FV2lOzfgtekU1jtlLYeAtbWyGnrdJtcvEC3ngqOKNwJf7IgN3Y5ITrZHiRXW4QJ5dWjk1CWG4bjIs pI9CIaH39JCk+adcZrjEXNOu3SMFyXXm6oY2ncJb67qyxQcvSQulminck6Q39aKueQzWyQtqCTZKU yX6hIyU5E3Q63+YWuSzLX7vJ/CuEHm4HkouS4wz6OuVjlazkbOgg80yEime5PRHLgpUOIjh9wH+S9 4aRtLjVQ==; Received: from wrigleys.postgresql.org ([2a02:16a8:dc51::60]) by mahout.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wyHu4-006PrE-2G for pgsql-bugs@lists.postgresql.org; Sun, 23 Aug 2026 23:47:04 +0000 Received: from localhost ([127.0.0.1] helo=wrigleys.postgresql.org) by wrigleys.postgresql.org with esmtp (Exim 4.98.2) (envelope-from ) id 1wyHu3-0000000H4id-2iSU for pgsql-bugs@lists.postgresql.org; Sun, 23 Aug 2026 23:47:03 +0000 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: BUG #19639: EXPLAIN (FORMAT JSON) emits a 309-digit cost value, and the node still reports "Disabled": false To: pgsql-bugs@lists.postgresql.org From: PG Bug reporting form Cc: manuelreyesbravo@gmail.com Reply-To: manuelreyesbravo@gmail.com, pgsql-bugs@lists.postgresql.org Date: Sun, 23 Aug 2026 23:46:57 +0000 Message-ID: <19639-9b1c9624a6034702@postgresql.org> X-Auto-Response-Suppress: All Auto-Submitted: auto-generated List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk The following bug has been logged on the website: Bug reference: 19639 Logged by: Manuel Reyes Bravo Email address: manuelreyesbravo@gmail.com PostgreSQL version: 19beta3 Operating system: Fedora 44, Linux 7.1.8, gcc 16.1.1, PostgreSQL bui Description: =20 Note up front: reproducing this needs a third-party index access method, but what I am reporting is the EXPLAIN output itself. Whatever the origin of the cost value, EXPLAIN (FORMAT JSON) emitting a 309-digit numeric literal breaks JSON consumers, and that part is in core. See "On attribution" at the end for what I did and did not verify. On 19beta3, EXPLAIN (FORMAT JSON) can emit a cost of DBL_MAX, rendered as a 309-digit number. serde_json rejects it with "number out of range", and I would expect most plan-analysis tooling to have the same problem, since there is no way for a client to consume it other than parsing the number as text. There is a second, separate oddity in the same output: the node carries "Disabled": false while having that saturated cost. On 18.6 the same query gets an ordinary cost and the disabled node is marked as disabled, which is what the disabled-nodes mechanism exists for. Reproducer ---------- Using pgvectorscale 0.9.0 ("diskann") with pgvector 0.8.6: CREATE EXTENSION vector; CREATE EXTENSION vectorscale; CREATE TABLE t_quant ( id SERIAL PRIMARY KEY, embedding vector(3), labels SMALLINT[] ); CREATE INDEX idx_quant ON t_quant USING diskann (embedding, labels); INSERT INTO t_quant (embedding, labels) VALUES ('[1,2,3]', '{1,2}'), ('[4,5,6]', '{1,3}'), ('[7,8,9]', '{2,3}'); SET enable_seqscan =3D 0; EXPLAIN (FORMAT JSON) SELECT * FROM t_quant WHERE labels && '{1}' ORDER BY labels, embedding <=3D> '[0,0,0]'; Ordering by labels first is the point: the index cannot satisfy that ordering, so with enable_seqscan off the only remaining plan is a penalized one. 19beta3: "Node Type": "Sort" "Total Cost": 179769313486231570814527423731704356798... (309 digits) "Disabled": false "Node Type": "Index Scan" "Total Cost": 179769313486231570814527423731704356798... (309 digits) "Disabled": false 18.6 (same extension, same schema, same query): "Node Type": "Sort" "Total Cost": 20.64 "Disabled": false "Node Type": "Seq Scan" "Total Cost": 20.63 "Disabled": true The text format shows the same value, with the cost running off the line. Two issues, I believe --------------------- 1. Regardless of how the cost became that large, EXPLAIN (FORMAT JSON) producing a 309-digit numeric literal is a problem in itself. JSON consumers are not prepared for it. 2. "Disabled": false together with a saturated cost is self-contradictory. Since the disabled-nodes mechanism was introduced precisely so that disabling a node no longer required inflating its cost, seeing both suggests something is not going through that mechanism. On attribution -------------- What I measured: 19beta3 emits this and 18.6 does not, with identical extension code, schema and query. What I did not determine: where the value originates. It is possible that the AM's amcostestimate returns a very large cost and that 19 propagates it while 18 never generated that path at all (18 picks a sequential scan instead). So I am not claiming the root cause is in core -- but issue 1 seems worth addressing either way, and issue 2 looks like a genuine inconsistency in the output. Versions tested --------------- PostgreSQL 19beta3, built from source: as shown above PostgreSQL 18.6, built from source with the same compiler and flags: normal costs Happy to dig further if someone points me at the right place to look.