On Sun, Jun 21, 2026 at 7:53 PM vignesh C <[email protected]> wrote: > > While attempting to log a conflict, a concurrent ALTER SUBSCRIPTION > can change the conflict logging destination from all to log. In this > scenario, the apply worker may already have cached the conflictlogdest > information, including the OID of the current conflict log table. > However, the concurrent ALTER SUBSCRIPTION drops the conflict log > table as part of the destination change: > +Relation > +GetConflictLogDestAndTable(ConflictLogDest *log_dest) > +{ > + Oid conflictlogrelid; > + > + /* > + * Convert the text log destination to the internal enum. > MySubscription > + * already contains the data from pg_subscription. > + */ > + *log_dest = GetConflictLogDest(MySubscription->conflictlogdest); > + > + /* Quick exit if a conflict log table was not requested. */ > + if (!CONFLICTS_LOGGED_TO_TABLE(*log_dest)) > + return NULL; > + > + conflictlogrelid = MySubscription->conflictlogrelid; > + > + Assert(OidIsValid(conflictlogrelid)); > + > + return table_open(conflictlogrelid, RowExclusiveLock); > +} > > As a result, when the apply worker later attempts to open the cached > conflict log table, table_open() fails because the relation has > already been dropped. This causes the error handling path itself to > fail before the conflict record can be written to either the conflict > log table or the server log. > > In such cases, the conflict record is effectively lost and is not > logged anywhere. For example: > 2026-06-21 19:31:13.592 IST [263598] LOG: logical replication apply > worker for subscription "sub1" has started > 2026-06-21 19:32:26.731 IST [263598] ERROR: could not open relation > with OID 16405 > 2026-06-21 19:32:26.731 IST [263598] CONTEXT: processing remote data > for replication origin "pg_16404" during message type "INSERT" for > replication target relation "public.t1" in transaction 698, finished > at 0/017D39A0 > 2026-06-21 19:32:26.735 IST [263471] LOG: background worker "logical > replication apply worker" (PID 263598) exited with exit code 1 > > Ideally, failure to access the conflict log table should not prevent > the conflict from being reported in the server log. This issue is > present with the v52 version. I have not yet checked if Amit's recent > patch posted a few minutes ago at [1] handles this issue. >
There are two places in the patch from where we LOG/Insert the conflict data. First is ReportApplyConflict() where we LOG if the conflict arises from a non-ERROR path (aka conflicts other INSERT/UPDATE_EXISTS). In that case, the conflict data will be logged even when we fail to insert into CLT. Second is the place for conflicts that arose as ERRORs (aka INSERT/UPDATE_EXISTS), where the conflict information will be logged along with insert failure as CONTEXT. Can you please verify your test based on this input and share your findings and thoughts? -- With Regards, Amit Kapila.
