Troubleshooting and FAQ
Start with the task's status and its Logs tab: errors name the setting to change. This page collects the common ones.
Where to look
- The task's state.
failedis a configuration problem (fix and start again);retryingis transient and resolves itself;heldis a safety guard waiting for you. - The task's Logs tab and the error under its status.
- The service log (
journalctl -u meilisearch-cdc,docker logs cdc); setCDC_LOG_LEVEL=debugfor more. - Test connection in the task wizard, and the connector's last test.
Source errors
| Message (excerpt) | Cause and fix |
|---|---|
postgres: wal_level is "replica" but logical replication needs "logical" | Set wal_level = logical and restart PostgreSQL. PostgreSQL. |
create replication slot … (the user needs the REPLICATION attribute and a free max_replication_slots entry) | Grant REPLICATION; raise max_replication_slots; drop unused cdc_* slots. |
replication slot "cdc_…" is active for PID … | Another consumer (often a second installation or a duplicate task id) holds the slot. Stop it or use another slot. |
has no primary key; add one or run ALTER TABLE … REPLICA IDENTITY FULL | Add a primary key, or set REPLICA IDENTITY FULL and mapping.primaryKey. |
mysql: binlog_format is MIXED but change capture needs ROW / binlog_row_image is MINIMAL … / binary logging is disabled | Fix the server config and persist it. MySQL. |
(grant REPLICATION SLAVE, REPLICATION CLIENT ON *.*) | Grant the replication privileges to the CDC user. |
mongodb: change streams need a replica set or sharded cluster | Start mongod --replSet rs0 and run rs.initiate(). MongoDB. |
sqlserver: SQL Server Agent is stopped, so the CDC capture job does not run | Start the Agent (MSSQL_AGENT_ENABLED=true in containers). SQL Server. |
change data capture is not enabled for database … / is not tracked by change data capture | Run the printed sp_cdc_enable_db / sp_cdc_enable_table. |
dynamodb: table … has no stream | Enable a stream with NEW_AND_OLD_IMAGES. DynamoDB. |
cockroachdb: changefeeds need rangefeeds … | SET CLUSTER SETTING kv.rangefeed.enabled = true as an admin. |
kafka: topic "…" does not exist | Use the exact Debezium topic name. |
sqlpoll: source.cursorColumn is required | Choose a cursor column. SQL polling. |
"source position lost … starting a full resync"
Not an error to fix: the stored position no longer exists on the source (a purged binlog, an invalidated or dropped replication slot, an oplog that rolled over, an expired DynamoDB shard, a trimmed Redis stream, SQL Server change rows removed by cleanup, a position older than CockroachDB's GC window). The task copies everything again, with zero-downtime resync if enabled. If it happens often, keep tasks running or extend the source's log retention.
The task is held
A safety guard refused a risky batch; nothing was applied.
safety hold: a single batch would delete 5000 of 8000 documents (62% > 20% limit): check whether the source really deleted those rows. If yes, raisemaxDeleteRatio(or set it to 0) and Resume, or Resync.safety hold: the source table was truncated; enable safety.allowTruncate or resync the task: decide whether the index should be emptied too.
See safety guards.
Meilisearch errors
| Message (excerpt) | Cause and fix |
|---|---|
index primary key mismatch: index "x" uses "sku" but the task writes "id" … | Use another index, change mapping.primaryKeyField, or resync with zero-downtime enabled. Primary key guard. |
task "x" already writes index "y" with primary key "z" (409) | Two tasks on one index must use the same primary key field. |
invalid_api_key, missing_authorization_header, HTTP 401/403 | Fix the destination's API key and its permissions. API key permissions. |
no Meilisearch destination is configured: add one first | Add a destination, or set MEILI_URL. |
Documents in the DLQ with invalid_document_id, invalid_document_geo_field… | See Dead letter queue. |
409 "single instance mode: MEILI_URL is set …"
With MEILI_URL set, the service writes only to that instance, and creating, deleting or switching destinations is refused. Unset MEILI_URL and restart to manage destinations in the dashboard. See single-instance mode.
Email does not send
| Message (excerpt) | Fix |
|---|---|
the server sent no greeting: it probably expects TLS from the start; use port 465 with TLS, or check the port | Port 465 needs TLS mode (or auto). |
the server does not speak TLS on this port; use STARTTLS on port 587 | Use port 587 with STARTTLS (or auto). |
the server does not support STARTTLS, so the password would be sent in plain text; use port 465 with TLS | Use TLS, or a relay without authentication with mode none. |
Links in emails point to http://127.0.0.1:8080 | Set the public URL in Settings → Email or CDC_PUBLIC_URL. |
Dashboard problems
- "Offline" in the top bar behind a proxy: the proxy buffers Server-Sent Events. See Reverse proxy and TLS.
403 cross-origin request refusedon every save: the proxy changes theHostheader; forward it unchanged.- Signed out after a restart: sessions survive restarts (they are stored); check that the data directory is persistent.
429 too many attempts: wait 15 minutes or restart the service; behind a proxy enableCDC_TRUST_PROXYso one IP does not stand for everyone.- Forgot the admin password:
meilisearch-cdc admin users reset-password --email … --generate. See recovery recipes.
The service does not start
- The database is locked: another process (a second instance, or the CLI working offline) has
cdc.dbopen. Run one instance per data directory. cannot decrypt secret/value was encrypted with a key that is not configured: the key changed. Provide the old key asCDC_SECRET_KEY, or asCDC_SECRET_KEY_PREVIOUSto rotate. See key rotation.task …: …then exit: the declarative tasks file has an error. See Declarative tasks file.- Permission denied on
/datain Docker: a bind mount not writable by uid 65532. See Docker.
FAQ
- Does it need Kafka or Debezium?
- No. Most sources are read directly. Kafka is one optional source, for databases only Debezium supports.
- Can one table feed several Meilisearch instances?
- Yes: create one task per destination on the same connector and table. For PostgreSQL each task has its own slot.
- Can several tables feed one index?
- Yes, with the same primary key field and the
upsertwrite mode, so each task merges its fields. Static fields help tell sources apart. - What delivery guarantee does it give?
- At-least-once with idempotent writes: a change may be applied twice after a crash, never lost, and applying it twice gives the same document.
- Can I run two replicas for high availability?
- No. The state store is single-writer; run one instance and let your orchestrator restart it. Checkpoints make restarts cheap.
- Does it change my database?
- Only for PostgreSQL (a replication slot and, unless you name one, a publication per task) and CockroachDB (it may enable
kv.rangefeed.enabledif allowed). Deleting a PostgreSQL task with drop source objects removes them. - How do I move an installation to another server?
- Stop it, copy the data directory (with
secret.key, or keep the sameCDC_SECRET_KEY), start it there. See Backups.