{"record":{"id":"c0d83062ee6a3c65","repo":"apache/seatunnel","slug":"illegal-argument-c0d830","errorCode":"ILLEGAL_ARGUMENT","errorMessage":"Unable to compare bson values between %s and %s","messagePattern":"Unable to compare bson values between (.+?) and (.+?)","errorType":"error_code","errorClass":"MongodbConnectorException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-mongodb/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/mongodb/utils/BsonUtils.java","lineNumber":103,"sourceCode":"                return compareBooleans(o1.asBoolean().getValue(), o2.asBoolean().getValue());\n            case DATE_TIME:\n                return compareDateTimes(o1.asDateTime().getValue(), o2.asDateTime().getValue());\n            case TIMESTAMP:\n                return compareTimestamps(o1.asTimestamp().getValue(), o2.asTimestamp().getValue());\n            case BINARY:\n                return compareBsonBinary(o1.asBinary(), o2.asBinary());\n            case OBJECT_ID:\n                return o1.asObjectId().compareTo(o2.asObjectId());\n            case DOCUMENT:\n            case DB_POINTER:\n                return compareBsonDocument(toBsonDocument(o1), toBsonDocument(o2));\n            case ARRAY:\n                return compareBsonArray(o1.asArray(), o2.asArray());\n            case JAVASCRIPT_WITH_SCOPE:\n                return compareJavascriptWithScope(\n                        o1.asJavaScriptWithScope(), o2.asJavaScriptWithScope());\n            default:\n                throw new MongodbConnectorException(\n                        ILLEGAL_ARGUMENT,\n                        String.format(\"Unable to compare bson values between %s and %s\", o1, o2));\n        }\n    }\n\n    private static int compareBsonValues(BsonValue v1, BsonValue v2) {\n        return compareBsonValue(v1, v2, false);\n    }\n\n    private static int compareBsonNumbers(BsonNumber n1, BsonNumber n2) {\n        Decimal128 decimal1 = getDecimal128FromCache(n1);\n        Decimal128 decimal2 = getDecimal128FromCache(n2);\n        return decimal1.compareTo(decimal2);\n    }\n\n    private static int compareStrings(String s1, String s2) {\n        return getStringFromCache(s1).compareTo(getStringFromCache(s2));\n    }","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-cdc/connector-cdc-mongodb/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/mongodb/utils/BsonUtils.java#L85-L121","documentation":"BsonUtils.compareBsonValue implements MongoDB's BSON comparison order but only covers the types it handles in its switch (numbers, strings, documents, arrays, timestamps, etc.). When both values fall through to the default branch — e.g. compared types are of different BSON categories or an unhandled type like BINARY/SYMBOL — it cannot produce an ordering and throws ILLEGAL_ARGUMENT.","triggerScenarios":"compareBsonValue(o1, o2) invoked with BsonValues whose BsonType is not one of the handled cases (e.g. BINARY vs STRING, SYMBOL, UNHANDLED); recursively reached via compareBsonValues, compareBsonDocument (comparing field values of different types), compareBsonArray (mismatched element types), or smallestValueOfArray on arrays with heterogeneous element types.","commonSituations":"Incremental snapshot key comparison over a shard key or document field whose BSON type changed between documents (e.g. a field that was a string becomes binary); resume-token or split computation touching mixed-type arrays; data written by an older driver with legacy types (Symbol).","solutions":["Ensure the compared field(s) have a consistent BSON type across all documents (normalize the source data or the extraction logic)","Extend compareBsonValue to handle the missing BsonType cases (add switch branches following MongoDB's type-order, e.g. via BsonUtils.typeOrder)","Log the two BsonValues and their BsonTypes to identify which type pair is unhandled and normalize before comparison"],"exampleFix":"// before\nthrow new MongodbConnectorException(ILLEGAL_ARGUMENT,\n    String.format(\"Unable to compare bson values between %s and %s\", o1, o2));\n// after (handle binary)\ncase BINARY:\n    return o1.asBinary().getData().length != o2.asBinary().getData().length\n        ? Integer.signum(o1.asBinary().getData().length - o2.asBinary().getData().length)\n        : ByteBuffer.wrap(o1.asBinary().getData()).compareTo(ByteBuffer.wrap(o2.asBinary().getData()));","handlingStrategy":"type-guard","validationCode":"if (!bsonValue.isNumber() && !bsonValue.isString() && !bsonValue.isDocument()\n    && !bsonValue.isArray() && !bsonValue.isDateTime() && !bsonValue.isTimestamp()) {\n    // normalize or skip before comparison\n}","typeGuard":"boolean comparable(BsonValue v) {\n    BsonType t = v.getBsonType();\n    return t == BsonType.DOUBLE || t == BsonType.INT32 || t == BsonType.INT64\n        || t == BsonType.DECIMAL128 || t == BsonType.STRING || t == BsonType.DOCUMENT\n        || t == BsonType.ARRAY || t == BsonType.DATE_TIME || t == BsonType.TIMESTAMP;\n}","tryCatchPattern":"try {\n    int cmp = BsonUtils.compareBsonValue(a, b);\n} catch (MongodbConnectorException e) {\n    log.warn(\"Uncomparable BSON types: {} vs {}\", a.getBsonType(), b.getBsonType());\n    // fall back to typeOrder comparison or skip the record\n}","preventionTips":["Enforce consistent BSON types on fields used as comparison/split keys","Avoid legacy BSON types (Symbol, undefined) in source data","Test comparisons against documents with heterogeneous field types"],"tags":["mongodb","bson","comparison","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}