CDC Sink: Troubleshooting
-
Use this article to diagnose common CDC Sink task problems and find the relevant recovery steps.
-
In this article:
Task fails to start
Symptom:
Task remains in Error state immediately after creation.
Common causes:
-
Invalid connection string
Verify that the connection string name matches a SQL connection string defined for the database. -
Connection refused
The source database is unreachable from the RavenDB server. Verify host, port, and firewall rules. -
Authentication failure
The credentials in the connection string are incorrect or the source-database user does not have the required permissions. For PostgreSQL, see Permissions and Roles. -
PostgreSQL WAL level not set to
logical
CDC Sink requires logical replication enabled on the PostgreSQL source. See WAL Configuration.
Check the error message in the Notification Center (bell icon in Studio) for the specific failure reason.
Task enters error state
Symptom:
Task was running, then stopped with an error.
Common causes:
-
PostgreSQL replication slot issue
Verify that the configured slot exists and uses thepgoutputplugin.If a slot with the task's configured name already exists but uses a different plugin, CDC Sink fails to start with an error such as "Replication slot '<name>' exists but uses plugin '<plugin>' instead of 'pgoutput'".
Drop the conflicting slot so CDC Sink can recreate it withpgoutput(see Dropping a replication slot).
To use a different slot name, delete the task and create a new one with a distinctSlotName.If the slot was dropped and recreated, CDC Sink may detect that the slot starts after the task's saved LSN;
changes in that gap cannot be recovered from the slot. -
Source table schema changed
Mapped column changes, renamed columns, or SQL Server CDC schema changes can make the task enter fallback mode or require configuration/source-side updates. See Source Schema Changes. -
PostgreSQL replication lag too large
If CDC Sink falls behind, the PostgreSQL replication slot can retain WAL segments and consume disk space.
Check slot lag and relevant PostgreSQL WAL-retention settings, such asmax_slot_wal_keep_size. -
Persistent connection failure
The source has been unreachable through multiple retry cycles. The first fallback delay is 5 seconds; subsequent retry delays roughly double up to theCdcSink.MaxFallbackTimeInSecbase cap (default 15 minutes), with small jitter. Restore connectivity and the task resumes automatically on the next retry.
Documents not appearing
Symptom:
SQL rows exist but corresponding RavenDB documents are not created.
Check:
-
Initial load still running
CDC Sink scans configured tables before it starts streaming captured changes.
For large tables, rows that have not been scanned yet will not appear. Check the task progress in Studio. -
SkipInitialLoad = true
If the task was created withSkipInitialLoad, existing source rows are not scanned.
They appear only if they were already loaded into RavenDB or are later changed in the source database. -
Task or table is disabled
Verify the task state isEnabledorPartiallyEnabled, notDisabled,
and that the table'sDisabledflag is not set totrue. -
Primary-key columns are wrong
PrimaryKeyColumnsare used to build the RavenDB document ID.
Verify they name source columns that exist, uniquely identify the row, and are included inColumns. -
Expected columns are not mapped
Only columns listed inColumnsare written as document properties.
Add mappings for any source columns that should appear in the document.
Embedded items missing or incorrect
Symptom:
Parent document exists but embedded array/map is empty or items are missing.
Check:
-
JoinColumnsmismatch
JoinColumnsmust contain the embedded table columns whose values identify the direct parent row.
CDC Sink pairs them with the parent'sPrimaryKeyColumnsby position, so the count and order must match. -
Embedded
PrimaryKeyColumnsare wrong
ForArrayandMapembedded tables, these columns identify the item inside the parent's array or map. If they are incomplete or wrong, UPDATE events can create duplicates and DELETE events may not find the item to remove. -
DELETE event missing routing columns For PostgreSQL embedded table deletes, CDC Sink needs the old row values for both the join columns and the embedded item's primary-key columns. If the join columns are not part of the table's primary key, configure
REPLICA IDENTITYso DELETE events include them. See REPLICA IDENTITY. -
Embedded
Typechanged after data was written
Typecontrols whether embedded data is stored as anArray,Map, orValue. If you change it after documents already exist, migrate or re-process existing documents so the property has a consistent shape.
DELETE not applied
Symptom:
A source row was deleted, but the RavenDB document or embedded item still exists.
Check:
-
OnDelete.IgnoreDeletes = true
When this flag is set, CDC Sink skips the automatic document delete or embedded-item removal.
IfOnDelete.Patchis also configured, the patch still runs, but the item is kept unless the script removes it explicitly. -
PostgreSQL DELETE event missing routing columns (embedded tables)
For embedded table deletes, CDC Sink needs old row values that identify the parent document and the embedded item. If those columns are not covered by the table's primary key or configuredREPLICA IDENTITY,
the DELETE event may not contain enough data to route the delete. See REPLICA IDENTITY. -
Delete patch keeps the data intentionally
ReviewOnDelete.Patchfor archive or soft-delete logic, such as setting anArchivedflag instead of deleting the document or embedded item.
Patch errors
Symptom:
Task enters error state with a message referencing a JavaScript patch failure.
Check:
-
Script syntax or runtime error
Test the script with the CDC Sink task's Test tool. The test runs CDC Sink mapping and the relevantPatchorOnDelete.Patchagainst source rows without saving documents. -
Missing values in the patch context
$oldcan benullfor new documents/items, and DELETE events may not include every source column in$row.
Use optional chaining and nullish coalescing, for example:$old?.Amount ?? 0. -
load()returnsnull
A document loaded withload(id)may not exist yet.
Guard the result before reading from it:
- javascript
const related = load("Collection/123");
if (related) {
this.RelatedName = related.Name;
}
- Step limit exceeded
Patch scripts have a step quota controlled byPatching.MaxStepsForScript(default10_000).
Long loops, repeatedload()calls, or large in-script computations can exceed it.
See the configuration reference for this setting.
Source schema changes
-
Adding, removing, renaming, or retyping columns in source tables can affect CDC Sink differently depending on the database engine.
-
PostgreSQL handles many changes transparently, MySQL can detect many changes but has positional and type-code limitations, and SQL Server requires an explicit capture-instance procedure for schema changes.
-
See Source Schema Changes for the full guide, including per-engine behavior, examples, recovery steps, and the SQL Server procedure.
Partial export/import and state loss
Symptom:
After importing a database export, CDC Sink re-reads all data from the source database from the beginning,
performing a full initial load even though the task configuration is present and the data already exists in RavenDB.
Cause:
CDC Sink stores two separate pieces of information:
- Task configuration
Stored in the cluster-wide database record.
It is included by default when theCdcSinksdatabase-record item is exported/imported. - Processing state
Stored as a document named@cdc-states/<task name>in the@cdc-statessystem collection.
This tracks the last processed source-database change position (LastLsn) and per-table initial-load progress.
If you export/import the task configuration but skip documents, skip system documents, or exclude the @cdc-states collection,
the task configuration is restored but the processing state document is missing.
When CDC Sink starts with a valid configuration and no matching state document, it starts fresh:
it captures a new source checkpoint, performs a full initial load of the configured enabled tables,
and then streams changes from that checkpoint.
For large source databases,
the new initial load can take significant time and place heavy load on both the source database and RavenDB.
How to avoid this:
- Include documents in the export/import, including the
@cdc-statescollection. - If using Smuggler or the REST API for selective export/import,
make sure system documents are included and the@cdc-statescollection is not filtered out. - Imported tasks are disabled by default.
Before enabling the task, verify that the matching@cdc-states/<task name>document was imported. - If the state document is missing but the target RavenDB data is already up to date,
set
SkipInitialLoad = truebefore the task's first start. If the task has already started, recreate it withSkipInitialLoad = true.
There is no supported way to manually set the last LSN position.
Although the state document in @cdc-states can technically be edited, doing so is risky:
an incorrect LSN can skip changes, replay changes from the wrong point, or produce inconsistent documents.
If the state document is lost, the safest options are to re-read from the beginning or start with SkipInitialLoad
when you are sure the target data is already up to date.
Shared replication slot across databases
Symptom (PostgreSQL):
After copying a CDC Sink task to a second database (via export/import or backup/restore),
one of the two tasks sits in fallback mode with an error like:
Process is in error recovery (fallback mode). Last error: <timestamp>. Next retry in: 464s.
Cause:
Export/import and backup/restore copy the task configuration verbatim,
including the immutable SlotName and PublicationName.
A PostgreSQL logical replication slot can be consumed by only one active connection at a time. When two enabled CDC Sink tasks point to the same slot, one task attaches to the slot and the other enters error-recovery (fallback) mode.
While the second task cannot attach, it does not apply new source changes.
Processing resumes only after that task can connect to the slot on a later retry.
Resolution:
- Keep the task enabled in only one database at a time when the configuration is shared.
For export/import, imported tasks are disabled by default;
for restore, useDisableOngoingTasksor disable the task on one database before both can run. - To run the task against both databases at once, give each copy its own dedicated slot and publication
(set a distinctSlotName/PublicationNameinCdcSinkPostgresSettingsbefore enabling the copy).