Symptoms: Tables from MySQL are not appearing in DuckDB after sync.
Solution 1: Check Excluded Tables
Cause: Tables may be in the EXCLUDED_TABLES configuration.
# Check .env filecat .env | grep EXCLUDED_TABLES# Remove table from exclusion listEXCLUDED_TABLES=old_table,temp_table # Remove the table you want to sync# Restart and trigger syncdocker-compose restart duckdb-servercurl -X POST http://localhost:3001/api/sync/full
Solution 2: Verify Table Exists in MySQL
Cause: Table may not exist or may be in a different database.
# List all MySQL tablesdocker exec duckling-server node scripts/mysql.js "SHOW TABLES"# Check specific tabledocker exec duckling-server node scripts/mysql.js "DESCRIBE table_name"
curl -X POST http://localhost:3001/api/sync/table/table_name
Solution 2: Check Watermark Boundaries
Cause: Records at exact watermark boundary may be missed.
Duckling uses >= operator (not >) to prevent boundary issues. This means the last synced record is re-processed each sync (safely handled by INSERT OR REPLACE).
# Verify watermark for tablecurl -X POST http://localhost:3001/api/query \ -H "Content-Type: application/json" \ -d '{"sql": "SELECT * FROM sync_log WHERE table_name = 'table_name' ORDER BY created_at DESC LIMIT 1"}'
If watermark appears stuck, reset it:
# Reset watermarkcurl -X POST http://localhost:3001/api/query \ -d '{"sql": "DELETE FROM sync_log WHERE table_name = 'table_name'"}'# Trigger full synccurl -X POST http://localhost:3001/api/sync/table/table_name
Solution 3: Force Full Sync
Cause: Incremental sync may have failed silently.
# Trigger full sync for specific tablecurl -X POST http://localhost:3001/api/sync/table/table_name# Or full sync for all tablescurl -X POST http://localhost:3001/api/sync/full
No Primary Key: Tables without primary keys can accumulate duplicates. The INSERT OR REPLACE upsert logic requires a primary key to identify duplicate records.
# Drop and recreatecurl -X POST http://localhost:3001/api/query \ -d '{"sql": "DROP TABLE table_name"}'curl -X POST http://localhost:3001/api/sync/table/table_name
Solution 2: Verify Deduplication Views
For fact tables (append-only), Duckling uses view-level deduplication:
# Check for duplicatescurl -X POST http://localhost:3001/api/query \ -d '{"sql": "SELECT COUNT(*) as total, COUNT(DISTINCT id) as unique FROM table_name"}'# If duplicates exist, query the deduplicated viewcurl -X POST http://localhost:3001/api/query \ -d '{"sql": "SELECT * FROM table_name_dedup"}'
Symptoms: Crash or error when syncing tables with very large unsigned BIGINT values.
Known Limitation: BIGINT UNSIGNED values above 9,223,372,036,854,775,807 (BIGINT_MAX) will overflow DuckDB’s signed BIGINT type and crash the appender.
Solution: Use a smaller unsigned type or change to signed BIGINT:
-- MySQL: Change to signed BIGINTALTER TABLE table_name MODIFY large_id BIGINT SIGNED;-- Or use DECIMAL for extremely large numbersALTER TABLE table_name MODIFY large_id DECIMAL(20,0);
Symptoms: Binary columns (BLOB, BINARY, VARBINARY) not updating during incremental sync or CDC.
Binary Types & CDC: Binary types break the INSERT OR REPLACE SQL path used by CDC updates. These types are only supported via full-sync Appender path.
Solution: Use full sync for tables with binary columns:
# Disable incremental sync for specific table# (requires code modification)# Or trigger periodic full syncs# Schedule via cron or external schedulercurl -X POST http://localhost:3001/api/sync/table/table_with_blobs
Alternatively, exclude binary columns from incremental sync by using a separate table.
Symptoms: Spatial/geometry columns contain binary garbage in DuckDB.
Spatial Types Not Supported: MySQL spatial types (POINT, LINESTRING, POLYGON, GEOMETRY, etc.) fall through to VARCHAR with raw binary WKB representation.Tables with spatial columns will sync but the spatial data is not usable for spatial queries in DuckDB.
Solution: Exclude spatial tables or extract coordinates:
-- MySQL: Extract coordinates to separate columnsALTER TABLE locations ADD COLUMN lat DECIMAL(10,8), ADD COLUMN lng DECIMAL(11,8);UPDATE locations SET lat = ST_Y(location), lng = ST_X(location);
Then sync the lat/lng columns instead of the spatial type.
# List all configured databasescurl http://localhost:3001/api/databases# Check database ID matches query parametercurl 'http://localhost:3001/api/tables?db=correct_id'
Solution 2: Check databases.json
# View database configurationcat data/databases.json# Ensure database entry exists with correct ID
Solution 3: Test Database Connection
# Test connection to specific databasecurl -X POST http://localhost:3001/api/databases/{id}/test
# Compare MySQL vs DuckDB countscurl http://localhost:3001/api/sync/validate# Check specific tablecurl -X POST http://localhost:3001/api/query \ -d '{"sql": "SELECT COUNT(*) FROM table_name"}'docker exec duckling-server node scripts/mysql.js \ "SELECT COUNT(*) FROM table_name"