Troubleshooting
Common issues and their solutions.
ACF Select Update Is Rejected
Section titled “ACF Select Update Is Rejected”Symptom: A Rondo Club PATCH fails with rest_invalid_param for the acf parameter even though clearing a field is intentional.
Cause: ACF select, radio, and button-group REST schemas accept null for an empty value but reject an empty string when "" is not one of the configured choices.
Fix: Send null, not "", when clearing one of these fields. Keep the detailed data.params value from the WordPress error in the sync report so the offending field remains visible.
Duplicate Entries in Rondo Club
Section titled “Duplicate Entries in Rondo Club”Symptom: Hundreds of duplicate member posts appear in Rondo Club.
Cause: Sync was run from a local machine. Each machine has its own SQLite database tracking rondo_club_id mappings. The local database doesn’t know about entries created by the server, so it creates new ones instead of updating.
Fix:
# On the servernode tools/delete-duplicates.js --verbose # Dry run firstnode tools/delete-duplicates.js --apply # Delete duplicates (keeps oldest per KNVB ID)Prevention: All sync scripts enforce a server check that blocks local execution. Always sync from [email protected]:/home/rondo/.
Chromium Won’t Start
Section titled “Chromium Won’t Start”Symptom:
Error: browserType.launch: Executable doesn't existFix: Install/reinstall Chromium:
npx playwright install chromiumIf that doesn’t work, install system dependencies:
sudo apt-get install -y libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 \ libcups2 libdrm2 libdbus-1-3 libxkbcommon0 libatspi2.0-0 libxcomposite1 \ libxdamage1 libxfixes3 libxrandr2 libgbm1 libpango-1.0-0 libcairo2 libasound2TOTP Authentication Fails
Section titled “TOTP Authentication Fails”Symptom: Login to Sportlink fails with invalid OTP code.
Causes and fixes:
-
Wrong secret format:
SPORTLINK_OTP_SECRETmust be the base32 secret key, not the fullotpauth://URL. -
Clock drift: TOTP is time-sensitive. Check server clock:
Terminal window timedatectl statusIf the clock is off, fix with:
Terminal window sudo ntpdate pool.ntp.org
Sync Reports Not Arriving
Section titled “Sync Reports Not Arriving”Symptom: No email reports after cron runs.
Checks:
- Verify Lettermint credentials in
.env:Terminal window grep LETTERMINT .envgrep OPERATOR_EMAIL .env - Verify sender email is verified in the Lettermint dashboard.
- Test manually:
Terminal window node scripts/send-email.js logs/cron/sync-people-2026-01-15_08-00-00.log people
Lock File Prevents Sync
Section titled “Lock File Prevents Sync”Symptom:
Another people sync is running. Exiting.Cause: A previous sync was interrupted (e.g., server restart, OOM kill) and the flock lock file wasn’t released.
Fix:
rm /home/rondo/.sync-people.lock # Or whichever sync typeNote: This is safe because flock automatically releases on process termination. A stale lock file only persists if the process was killed in an unusual way.
Members Missing from Rondo Club
Section titled “Members Missing from Rondo Club”Symptom: Some members exist in Sportlink but don’t appear in Rondo Club.
Diagnosis:
# Check if member exists in local database
# Check Rondo Club mappingsqlite3 data/rondo-sync.sqlite "SELECT knvb_id, rondo_club_id, last_synced_at FROM rondo_club_members WHERE email = '[email protected]'"Possible causes:
- No
rondo_club_idyet: Member was downloaded but sync failed. Runscripts/sync.sh peopleto retry. - Invalid
rondo_club_id: The WordPress post was deleted. Fix with:Then re-run sync to recreate the member.Terminal window node tools/verify-rondo-club-data.js --fix --verbose - Member has no email: Sportlink members without an email address may be skipped.
Invalid rondo_club_id Mappings
Section titled “Invalid rondo_club_id Mappings”Symptom: Sync fails with 404 errors for specific members, or members appear to “recreate” every run.
Cause: The WordPress post was deleted outside the sync tool, but the local database still references the old post ID.
Fix:
# Verify which IDs are invalidnode tools/verify-rondo-club-data.js --verbose
# Fix by nullifying invalid IDs (they'll be recreated on next sync)node tools/verify-rondo-club-data.js --fix --verbose
# Or use validate-rondo-club-ids for a simpler checknode tools/validate-rondo-club-ids.js # Dry runnode tools/validate-rondo-club-ids.js --apply # Fix invalid IDsPhotos Not Syncing
Section titled “Photos Not Syncing”Symptom: Member photos show in Sportlink but not in Rondo Club.
Diagnosis:
# Check photo state distributionsqlite3 data/rondo-sync.sqlite "SELECT photo_state, COUNT(*) FROM rondo_club_members GROUP BY photo_state"
# Check consistency between files and databasenode tools/check-photo-consistency.js --verboseCommon issues:
-
Stuck in
pending_download: Photo URL may be expired. Fix:Terminal window # Re-scrape photo URLs via functions syncscripts/sync.sh functions# Then run people sync to download/uploadscripts/sync.sh people -
Files missing for
downloadedstate: Files were cleaned up but state wasn’t updated:Terminal window node tools/check-photo-consistency.js --fix -
Members with photos marked
no_photo: State got out of sync:Terminal window node tools/reset-photo-states.js # Dry runnode tools/reset-photo-states.js --apply # Fix states
Free Fields Missing After Functions Sync
Section titled “Free Fields Missing After Functions Sync”Symptom: FreeScout ID, VOG date, or financial block data disappears from Rondo Club after a daily functions sync.
Cause: This was a critical bug (fixed in commit 9d0136e): when the daily functions sync processed only a subset of members, it used clear + replace on database tables, wiping data for members not in the current run. The fix uses upsert-only for partial runs.
If data was wiped: Run a full functions sync to restore:
Orphaned Relationships
Section titled “Orphaned Relationships”Symptom: Relationships reference people who no longer exist.
Fix:
# Find orphaned relationshipsnode tools/cleanup-orphan-relationships.js --verbosenode tools/cleanup-orphan-relationships.js --fix # Remove them
# Find duplicate relationshipsnode tools/cleanup-duplicate-relationships.jsNote: As of v2.3, birthdays sync as acf.birthdate on person records and no longer use separate important_date posts.
Laposta Sync Shows Zero Changes
Section titled “Laposta Sync Shows Zero Changes”Symptom: show-laposta-changes shows no pending changes even though data has changed.
Cause: The prepare step may not have run. The sync pipeline runs in order: download → prepare → submit.
Fix:
# Re-prepare Laposta members from latest downloadnpm run prepare-laposta
# Check for changes nownpm run show-laposta-changesDatabase Corruption
Section titled “Database Corruption”Symptom: SQLite errors like “database is locked” or “malformed”.
Recovery options:
-
Database locked: Usually caused by a sync process that didn’t exit cleanly. Kill any lingering Node processes:
Terminal window pkill -f "node sync-" || true -
Database corrupted: The simplest recovery is to delete the database and re-run a full sync. The databases are derived from source systems and can be rebuilt:
Terminal window # Back up firstcp data/rondo-sync.sqlite data/rondo-sync.sqlite.bak# Delete and rebuild (this will create all members as new in Rondo Club!)# Only do this if you're certain - it may cause duplicate entriesrm data/rondo-sync.sqlitescripts/sync.sh allWarning: Deleting
data/rondo-sync.sqliteloses allrondo_club_idmappings. This means the next sync will create new WordPress posts instead of updating existing ones. Usetools/repopulate-rondo-club-ids.jsafterward to restore mappings:Terminal window node tools/repopulate-rondo-club-ids.js --verbose # Dry runnode tools/repopulate-rondo-club-ids.js # Apply