SEPURI-SAI-KRISHNA opened a new issue, #11720: URL: https://github.com/apache/seatunnel/issues/11720
### Search before asking - [x] I had searched in the [issues](https://github.com/apache/seatunnel/issues?q=is%3Aissue+label%3A%22bug%22) and found no similar issues. ### What happened `MultiTableSinkWriter.write` routes each row to a queue using: ```java index = Math.abs(object.hashCode()) % blockingQueues.size(); ``` `Math.abs(Integer.MIN_VALUE)` returns `Integer.MIN_VALUE` — it is still negative, because `-Integer.MIN_VALUE` is not representable as an `int`. When the queue count is not a power of two, the modulo result is therefore negative and `blockingQueues.get(index)` throws, failing the sink writer: ``` java.lang.IndexOutOfBoundsException: Index -2 out of bounds for length 3 at java.base/java.util.Objects.checkIndex(Objects.java:372) at java.base/java.util.ArrayList.get(ArrayList.java:459) at org.apache.seatunnel.api.sink.multitablesink.MultiTableSinkWriter.write(MultiTableSinkWriter.java:604) ``` Any primary key value whose `hashCode()` is `Integer.MIN_VALUE` triggers it. All of these do: | Primary key type | Value | |---|---| | `INT` | `-2147483648` | | `BIGINT` | `-9223372036854775808` (`Long.MIN_VALUE`) | | `STRING` | any string hashing to `Integer.MIN_VALUE`, e.g. `polygenelubricants` | Whether it actually throws depends on the queue count, which is `multi_table_sink_replica`: | `multi_table_sink_replica` | resulting index | |---|---| | 1, 2, 4, 8, 16 (powers of two) | 0 — safe | | 3 | -2 — throws | | 5 | -3 — throws | | 6 | -2 — throws | | 7 | -2 — throws | | 9 | -2 — throws | | 10 | -8 — throws | | 12 | -8 — throws | Since `multi_table_sink_replica` defaults to `1`, a default configuration is unaffected — the bug only surfaces once the option is tuned to a non-power-of-two value, which is presumably why it has gone unnoticed. It affects every multi-table sink, because the routing lives in `seatunnel-api` and is shared by all of them. This is the same defect class that was fixed for the file source split enumerator in #2921, which replaced `Math.abs(tp.hashCode()) % numReaders` with `(tp.hashCode() & Integer.MAX_VALUE) % numReaders`. That idiom is now used in 12 places across the codebase (Paimon, Kafka, DynamoDB, HBase, Fluss, Typesense, TiDB CDC, MongoDB, Iceberg, JDBC, Easysearch, and the Hazelcast metrics store). `MultiTableSinkWriter` is the last remaining site still using the unsafe form. ### SeaTunnel Version dev ### SeaTunnel Config ```conf sink { Jdbc { # ... any multi-table sink with a primary key ... multi_table_sink_replica = 3 } } with a source table whose primary key contains the value -2147483648. ``` ### Running Command ```shell ./bin/seatunnel.sh --config ./config/repro.conf -e local ``` ### Error Exception ```log java.lang.IndexOutOfBoundsException: Index -2 out of bounds for length 3 at java.base/java.util.Objects.checkIndex(Objects.java:372) at java.base/java.util.ArrayList.get(ArrayList.java:459) at org.apache.seatunnel.api.sink.multitablesink.MultiTableSinkWriter.write(MultiTableSinkWriter.java:604) ``` ### Zeta or Flink or Spark Version Zeta (engine-independent; the routing lives in seatunnel-api) ### Java or Scala Version Java 11 ### Screenshots _No response_ ### Are you willing to submit PR? - [x] Yes I am willing to submit a PR! ### Code of Conduct - [x] I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
