On Thu, 27 Aug 2026 at 20:26, Nathan Bossart <[email protected]> wrote: > > I don't fully understand the mechanics of this one, but here is a > reproducer: > > CREATE TABLE t (a INT PRIMARY KEY, b INT, c TEXT); > INSERT INTO t SELECT g, g, repeat('x', 1000) FROM generate_series(1, > 1000000) g; > CREATE UNIQUE INDEX i ON t (a); > ALTER TABLE t REPLICA IDENTITY USING INDEX i; > DROP INDEX i; > REPACK (CONCURRENTLY) t; > > -- in a separate session, while REPACK is still running > DELETE FROM t WHERE a = 1; > > This produces the following ERROR from the REPACK command: > > ERROR: incomplete delete info > CONTEXT: slot "pg_repack_34213", output plugin "pgrepack", in the change > callback, associated LSN 0/A6CC1ED0 > REPACK decoding worker > > I think this can be addressed by verifying the index exists in > check_concurrent_repack_requirements() and erroring out if it doesn't.
I think the issue is caused by the following: REPACK's check has the incorrect assumption that REPLICA IDENTITY USING INDEX either reverts to DEFAULT or falls back to the behaviour of DEFAULT if the identity index gets dropped, and thus uses GetRelationIdentityOrPK(), which hides a lack of replica identity index. The issue shows up due to the following garden path of data flows: 1. A table with REPLICA IDENTITY USING INDEX doesn't fall back to REPLICA IDENTITY DEFAULT once the identity index is dropped. 2. In the catcache, the table won't fall back to rd_replidindex = pkeyIndex when replident='i', but instead will set rd_replidindex=InvalidOid. See the tail end of RelationGetIndexList. 3. Then, in heap_delete, it calls ExtractReplicaIdentity() to find the key of the deleted tuple. 3a. ExtractR_I_() checks the identity key attributes from RelationGetIndexAttrBitmap(..., INDEX_ATTR_BITMAP_IDENTITY_KEY), which also only uses rd_replidindex, and doesn't fall back to the primary key index's attributes. 3b. If ExtractR_I_() doesn't have identity key attributes, it returns NULL 3c. heap_delete thus doesn't have any logical identity attributes to log, and treats the delete operation as any non-logical deletion when logging the data. 4. Finally, the DELETE record gets decoded, and the logical plugin finds out that no logical key data was included, and promptly ERRORs out. The attached patch is a blind shot that I suspect will fix the issue. Kind regards, Matthias van de Meent Databricks (https://www.databricks.com)
v1-0001-Repack-Fix-replica-identity-index-check.patch
Description: Binary data
