Thread

  1. Make the logical replication conflict messages more like each other

    Peter Smith <smithpb2250@gmail.com> — 2026-05-18T23:08:18Z

    Hi,
    
    (This was first suggested by me in thread [1], but it was deemed out
    of scope, so I have now separated it here.)
    
    I was looking at the many messages related to logical replication
    conflicts (in conflict.c, function errdetail_apply_conflict).
    Currently, the wording for the errmsgdetail seems a bit inconsistent
    to me. I felt that because all of these messages are closely related,
    they should all resemble each other more than they do now.
    
    ~~~
    
    CURRENT
    
    CT_INSERT_EXISTS
    CT_UPDATE_EXISTS
    CT_MULTIPLE_UNIQUE_CONFLICTS
    * Could not apply remote change: %s.\n
    * Could not apply remote change.\n
    - Key already exists in unique index \"%s\", modified locally in
    transaction %u at %s: %s.
    - Key already exists in unique index \"%s\", modified locally in
    transaction %u at %s.
    - Key already exists in unique index \"%s\", modified by origin \"%s\"
    in transaction %u at %s: %s.
    - Key already exists in unique index \"%s\", modified by origin \"%s\"
    in transaction %u at %s.
    - Key already exists in unique index \"%s\", modified by a
    non-existent origin in transaction %u at %s: %s.
    - Key already exists in unique index \"%s\", modified by a
    non-existent origin in transaction %u at %s.
    - Key already exists in unique index \"%s\", modified in transaction %u: %s.
    - Key already exists in unique index \"%s\", modified in transaction %u.
    
    CT_UPDATE_ORIGIN_DIFFERS
    - Updating the row that was modified locally in transaction %u at %s: %s.
    - Updating the row that was modified locally in transaction %u at %s.
    - Updating the row that was modified by a different origin \"%s\" in
    transaction %u at %s: %s.
    - Updating the row that was modified by a different origin \"%s\" in
    transaction %u at %s.
    - Updating the row that was modified by a non-existent origin in
    transaction %u at %s: %s.
    - Updating the row that was modified by a non-existent origin in
    transaction %u at %s.
    
    CT_UPDATE_DELETED
    * Could not find the row to be updated: %s.\n
    * Could not find the row to be updated.\n
    - The row to be updated was deleted locally in transaction %u at %s
    - The row to be updated was deleted by a different origin \"%s\" in
    transaction %u at %s
    - The row to be updated was deleted by a non-existent origin in
    transaction %u at %s
    - The row to be updated was deleted
    
    CT_UPDATE_MISSING
    * Could not find the row to be updated: %s.
    * Could not find the row to be updated.
    
    CT_DELETE_ORIGIN_DIFFERS
    - Deleting the row that was modified locally in transaction %u at %s: %s.
    - Deleting the row that was modified locally in transaction %u at %s.
    - Deleting the row that was modified by a different origin \"%s\" in
    transaction %u at %s: %s.
    - Deleting the row that was modified by a different origin \"%s\" in
    transaction %u at %s.
    - Deleting the row that was modified by a non-existent origin in
    transaction %u at %s: %s.
    - Deleting the row that was modified by a non-existent origin in
    transaction %u at %s.
    
    CT_DELETE_MISSING
    * Could not find the row to be deleted: %s.
    * Could not find the row to be deleted.
    
    ~~~
    
    Some proposed changes:
    e.g. Only some cases (CT_UPDATE_DELETED, CT_INSERT_EXISTS,
    CT_UPDATE_EXISTS, etc.) currently give the general reason, followed on
    the next line by the details for the conflict. I think all these
    conflict messages should use this pattern
    e.g. All errdetail messages should have a period to terminate them.
    e.g. Use more consistent wording for all conflicts: "The row to
    update", "The row to delete", etc.
    e.g. The words "the row to be updated" do not need to be repeated for
    the same conflict message.
    e.g. The suggested wording makes the messages much closer to the DOCS
    [2] descriptions
    
    (Compare the CURRENT messages above with the following SUGGESTIONS below)
    
    SUGGESTIONS (or something like this...)
    
    CT_INSERT_EXISTS
    CT_UPDATE_EXISTS
    CT_MULTIPLE_UNIQUE_CONFLICTS
    * The row to insert violates a constraint: %s.\n
    * The row to insert violates a constraint.\n
    * The row to update violates a constraint: %s.\n
    * The row to update violates a constraint.\n
    * The row to insert or update violates a constraint: %s.\n
    * The row to insert or update violates a constraint.\n
    - Key already exists in unique index \"%s\", modified locally in
    transaction %u at %s: %s.
    - Key already exists in unique index \"%s\", modified locally in
    transaction %u at %s.
    - Key already exists in unique index \"%s\", modified by origin \"%s\"
    in transaction %u at %s: %s.
    - Key already exists in unique index \"%s\", modified by origin \"%s\"
    in transaction %u at %s.
    - Key already exists in unique index \"%s\", modified by a
    non-existent origin in transaction %u at %s: %s.
    - Key already exists in unique index \"%s\", modified by a
    non-existent origin in transaction %u at %s.
    - Key already exists in unique index \"%s\", modified in transaction %u: %s.
    - Key already exists in unique index \"%s\", modified in transaction %u.
    
    CT_UPDATE_ORIGIN_DIFFERS
    * The row to update was modified by another origin.\n
    - It was modified locally in transaction %u at %s: %s.
    - It was modified locally in transaction %u at %s.
    - It was modified by a different origin \"%s\" in transaction %u at %s: %s.
    - It was modified by a different origin \"%s\" in transaction %u at %s.
    - It was modified by a non-existent origin in transaction %u at %s: %s.
    - It was modified by a non-existent origin in transaction %u at %s.
    
    CT_UPDATE_DELETED
    * The row to update was already deleted: %s.\n
    * The row to update was already deleted.\n
    - It was deleted locally in transaction %u at %s.
    - It was deleted by a different origin \"%s\" in transaction %u at %s.
    - It was deleted by a non-existent origin in transaction %u at %s.
    
    CT_UPDATE_MISSING
    * The row to update was not found: %s.
    * The row to update was not found.
    
    CT_DELETE_ORIGIN_DIFFERS
    * The row to delete was modified by another origin.\n
    - It was modified locally in transaction %u at %s: %s.
    - It was modified locally in transaction %u at %s.
    - It was modified by a different origin \"%s\" in transaction %u at %s: %s.
    - It was modified by a different origin \"%s\" in transaction %u at %s.
    - It was modified by a non-existent origin in transaction %u at %s: %s.
    - It was modified by a non-existent origin in transaction %u at %s.
    
    CT_DELETE_MISSING
    * The row to delete was not found: %s.
    * The row to delete was not found.
    
    ~~~
    
    Anyway, this is just a suggestion. I won't make the patch for this
    unless/until there is agreement that proceeding would be worthwhile.
    
    ======
    [1] https://www.postgresql.org/message-id/CAHut%2BPvicB-bAqo4XpsPOnr%3DLi_jop6i4kpcy%2BVK_MYsEFFeqg%40mail.gmail.com
    [2] https://www.postgresql.org/docs/devel/logical-replication-conflicts.html
    
    Kind Regards,
    Peter Smith.
    Fujitsu Australia.