Skip to content

fix: use UPSERT instead of CREATE for single-record AppendRecords#294

Open
andrewseddon wants to merge 1 commit intolibdns:masterfrom
andrewseddon:fix-append-records-upsert
Open

fix: use UPSERT instead of CREATE for single-record AppendRecords#294
andrewseddon wants to merge 1 commit intolibdns:masterfrom
andrewseddon:fix-append-records-upsert

Conversation

@andrewseddon
Copy link
Copy Markdown

Problem

When AppendRecords is called with a single record, it uses the Route53 CREATE action via createRecord(). This fails with an InvalidChangeBatch error if the ResourceRecordSet already exists:

Tried to create resource record set [name='_acme-challenge.example.com.', type='TXT'] but it already exists

This commonly happens with ACME DNS-01 challenges (e.g. via Caddy) when a _acme-challenge TXT record is left over from a previous attempt — for example after a container restart, failed cleanup, or when both the staging and production ACME servers attempt the challenge.

Fix

Remove the single-record special case in appendRecordSet() so all appends use the existing merge+UPSERT path (which was already used for multi-record appends). This correctly handles both new and existing record sets.

The multi-record path:

  1. Fetches existing records for the zone
  2. Finds any existing values for the same name+type
  3. Merges new records with existing ones
  4. Uses UPSERT to set the combined record set

This is one extra API call (ListResourceRecordSets) compared to the previous single-record path, but is correct and idempotent.

When AppendRecords is called with a single record, it previously used
the Route53 CREATE action which fails with InvalidChangeBatch if the
ResourceRecordSet already exists. This commonly happens with ACME DNS-01
challenges when a _acme-challenge TXT record is left over from a
previous attempt (e.g. after a container restart or failed cleanup).

The fix removes the single-record special case so all appends use the
same merge+UPSERT path that was already used for multi-record appends.
This is idempotent and handles both new and existing record sets
correctly.

Fixes the error:
  Tried to create resource record set [name='_acme-challenge.example.com.',
  type='TXT'] but it already exists
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant