Skip to content

fix(lotw): confirmations never applied - duplicate qsl_lotw_date assignment (42601)#218

Merged
patrickrb merged 2 commits into
mainfrom
fix/lotw-download-duplicate-column
Jul 13, 2026
Merged

fix(lotw): confirmations never applied - duplicate qsl_lotw_date assignment (42601)#218
patrickrb merged 2 commits into
mainfrom
fix/lotw-download-duplicate-column

Conversation

@patrickrb

Copy link
Copy Markdown
Owner

Problem

"LoTW confirmations never come back." The bulk download route builds a dynamic UPDATE contacts SET ... that assigned qsl_lotw_date twice — seeded as NOW()::date and appended again with LoTW's qsl_rcvd_date (returned for nearly every confirmation when qso_qsl=yes). Postgres rejects multiple assignments to the same column in one UPDATE (error 42601), so the first matched confirmation threw, the outer catch marked the whole download failed, and every confirmation in the batch was discarded. Downloads have been silently failing whenever there was anything to apply.

Fix

  • Assign qsl_lotw_date exactly once: LoTW's own QSL date when present, else today.
  • Per-row try/catch around each confirmation apply — one bad row can no longer zero out a batch. Failures are counted, logged with the contact id, and summarized in lotw_download_logs.error_message and the response.
  • Advance the incremental cursor (stations.lotw_last_qsl_rcvd_date) only from confirmations that actually applied, and read it back as qso_qslsince for non-manual downloads — the column was maintained but never used, so cron downloads re-fetched the full history every run. (The QSL-since date is deliberately NOT applied to the local contacts filter: confirmations arrive for arbitrarily old QSOs.)

Verification

  • npm run lint / npm run typecheck / npm run build clean.
  • First PR of the sync-reliability series (LoTW download fix → QRZ auto-sync rewrite → cron auth → unified hourly sync cron → sync activity UI → UTC parsing).

🤖 Generated with Claude Code

The dynamic UPDATE seeded qsl_lotw_date = NOW()::date and then appended a
second qsl_lotw_date assignment whenever LoTW returned qsl_rcvd_date (which
it nearly always does with qso_qsl=yes). Postgres rejects two assignments to
the same column in one UPDATE (42601), so the first matched confirmation
threw, the whole download was logged failed, and confirmations were never
applied.

- Assign qsl_lotw_date exactly once: LoTW's qsl_rcvd_date when present,
  otherwise today.
- Isolate per-row apply failures (try/catch + counter) so one bad row can no
  longer discard an entire batch; surface a failure summary in
  lotw_download_logs.error_message and the response.
- Advance the incremental cursor only from successfully applied
  confirmations, and use stations.lotw_last_qsl_rcvd_date as qso_qslsince
  for non-manual downloads (the column was written but never read back).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nodelog Ready Ready Preview, Comment Jul 13, 2026 5:11pm

Request Review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes LoTW download confirmation application failures caused by generating an invalid UPDATE statement (duplicate qsl_lotw_date assignment), which previously caused Postgres error 42601 and prevented any confirmations in a batch from being applied. The PR also improves sync reliability for scheduled/automatic runs by introducing incremental fetching and isolating per-confirmation apply errors.

Changes:

  • Ensure qsl_lotw_date is assigned exactly once during confirmation updates (prefer LoTW QSL date, else today).
  • Add per-row try/catch when applying confirmations so a single failing update doesn’t discard the whole batch; summarize partial failures into lotw_download_logs.error_message and API response.
  • Use stations.lotw_last_qsl_rcvd_date as qso_qslsince for non-manual downloads and only advance the cursor based on confirmations that actually applied.

Comment thread src/app/api/lotw/download/route.ts Outdated
When conf.qsl_rcvd_date was missing we wrote NOW()::date to the contact
but never recorded it in appliedQslDates, so lotw_last_qsl_rcvd_date
never advanced and incremental downloads refetched the same history.
Compute the fallback date in JS and record it like any other applied date.

Addresses Copilot review feedback on #218.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@patrickrb
patrickrb merged commit 7d6b94f into main Jul 13, 2026
7 checks passed
@patrickrb
patrickrb deleted the fix/lotw-download-duplicate-column branch July 13, 2026 17:39
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.

2 participants