Hi Sonal,

Thank you for the detailed writeup.

If I understand correctly, StreamSplitState will be updated in 
MongoDBRecordEmitter, so the resume token and starting timestamp should be 
updated in-place. Could you please file a minimal reproducible example to 
verify this bug?

The error log and large BSONObject issue seems irrelevant to the state recovery 
issue, maybe we should create individual JIRA tickets / PRs to trace and fix 
them.

Looking forward to your patch.

Best Regards,
Xiqian

> Sonal Maheshwari <[email protected]> 於 2026年10月19日 下午2:30 寫道:
> 
> Hi all,
> 
> I've found a bug in flink-connector-mongodb-cdc's error recovery and would
> like to contribute a fix. (JIRA account requested; I'll file a ticket once
> approved.)
> 
> When tryNext() fails with a code in INVALID_CHANGE_STREAM_ERRORS, the fetch
> task recreates the cursor in place [1], but builds the resume position
> from streamSplit.getStartingOffset()
> [2] -- which is set when the task starts and never advances. So the cursor
> reopens from task start and replays everything read since. In production
> this gave us a multi-day lag spike from one error.
> 
> For 280/286 it's worse: the timestamp fallback [3] also comes from the
> starting offset, so after "resume token too old" it retries from an even
> older point.
> 
> The error itself is also invisible: the only log line is a fixed WARN,
> "Change stream cursor has expired, trying to recreate cursor" [4], with no
> error code or message. With six codes going down this path, there's no way
> to tell from logs which one fired. We only found ours by patching that line
> to log the exception.
> 
> Our trigger turned out to be BSONObjectTooLarge (10334): with updateLookup,
> an update event can exceed 16MB even when the document doesn't. It's
> in the recreate
> list [5], but recreating can't help since the event itself is too large.
> 
> Proposed:
> 
> 1. Track the latest resume token (events + heartbeats) and reopen from
> it. Restart/restore
> behaviour is unchanged. Also log the error code and message.
> 
> 2. Separately, use $changeStreamSplitLargeEvent (MongoDB 6.0.9+) [6]
> and reassemble
> fragments in the fetch task.
> 
> I have patches for both. Feedback welcome.
> 
> Thanks,
> 
> Sonal
> 
> 
> [1]
> https://github.com/apache/flink-cdc/blob/abf18d7a87e6937984949901b77b87ce6def5a76/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mongodb-cdc/src/main/java/org/apache/flink/cdc/connectors/mongodb/source/reader/fetch/MongoDBStreamFetchTask.java#L115-L127
> 
> [2]
> https://github.com/apache/flink-cdc/blob/abf18d7a87e6937984949901b77b87ce6def5a76/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mongodb-cdc/src/main/java/org/apache/flink/cdc/connectors/mongodb/source/reader/fetch/MongoDBStreamFetchTask.java#L258-L259
> 
> [3]
> https://github.com/apache/flink-cdc/blob/abf18d7a87e6937984949901b77b87ce6def5a76/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mongodb-cdc/src/main/java/org/apache/flink/cdc/connectors/mongodb/source/reader/fetch/MongoDBStreamFetchTask.java#L279
> 
> [4]
> https://github.com/apache/flink-cdc/blob/abf18d7a87e6937984949901b77b87ce6def5a76/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mongodb-cdc/src/main/java/org/apache/flink/cdc/connectors/mongodb/source/reader/fetch/MongoDBStreamFetchTask.java#L117
> 
> [5]
> https://github.com/apache/flink-cdc/blob/abf18d7a87e6937984949901b77b87ce6def5a76/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mongodb-cdc/src/main/java/org/apache/flink/cdc/connectors/mongodb/source/utils/MongoUtils.java#L90-L98
> 
> [6]
> https://www.mongodb.com/docs/manual/reference/operator/aggregation/changeStreamSplitLargeEvent/

Reply via email to