-
Type:
Task
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: None
-
None
-
Replication
-
Fully Compatible
-
Repl 2026-04-13
-
None
-
None
-
None
-
None
-
None
-
None
-
None
I identified the following locations in our jstests where we call haystack.includes on some haystack and pass the result to assert:
./jstests/concurrency/fsm_workloads/txns/multi_statement_transaction/multi_statement_transaction_current_op.js|31 col 17| assert(acceptableReadConcernLevels.includes(transactionDocument.parameters.readConcern.level)); jstests/core/txns/commit_prepared_transaction_errors.js|64 col 1| assert(res.errmsg.includes("cannot provide commitTimestamp to unprepared transaction"), res); jstests/core/txns/multi_statement_transaction_command_args.js|57 col 1| assert(res.errmsg.includes("Transaction number requires a session ID")); jstests/core/txns/multi_statement_transaction_command_args.js|73 col 1| assert(res.errmsg.includes("'autocommit' field requires a transaction number")); jstests/core/txns/multi_statement_transaction_command_args.js|89 col 1| assert(res.errmsg.includes("'startTransaction' field requires 'autocommit' field")); jstests/core/write/bulk/bulk_write_non_transaction.js|412 col 5| assert(res.cursor.firstBatch[0].errmsg.includes("Constant values may only be specified for pipeline updates")); jstests/replsets/auth_coordinateCommitTransaction.js|117 col 5| assert(res.errmsg.includes("Unauthorized to set user digest"), res); jstests/replsets/ddl_ops_after_prepare_lock_failpoint.js|60 col 5| assert(testDB.getCollectionNames().includes(collToDrop)); jstests/replsets/ddl_ops_after_prepare_lock_failpoint.js|67 col 5| assert(testDB.getCollectionNames().includes(collToRenameFrom)); jstests/replsets/ddl_ops_after_prepare_lock_failpoint.js|68 col 5| assert(!testDB.getCollectionNames().includes(collToRenameTo)); jstests/replsets/log_wt_stats_during_secondary_oplog_application.js|45 col 1| assert(slowLogLine.includes("bytesRead")); jstests/replsets/not_primary_errors_returned_during_rollback_if_helloOk.js|61 col 1| assert(res.errmsg.includes("not master or secondary"), res); jstests/replsets/not_primary_errors_returned_during_rollback_if_helloOk.js|81 col 1| assert(res.errmsg.includes("not primary or secondary"), res); jstests/replsets/not_primary_errors_returned_during_rollback_if_helloOk.js|82 col 1| assert(!res.errmsg.includes("not master"), res); jstests/replsets/not_primary_errors_returned_if_client_sends_helloOk.js|30 col 1| assert(res.errmsg.includes("not master"), res); jstests/replsets/not_primary_errors_returned_if_client_sends_helloOk.js|41 col 1| assert(res.errmsg.includes("not master"), res); jstests/replsets/not_primary_errors_returned_if_client_sends_helloOk.js|68 col 1| assert(res.errmsg.includes("not primary"), res); jstests/replsets/not_primary_errors_returned_if_client_sends_helloOk.js|69 col 1| assert(!res.errmsg.includes("not master"), res); jstests/replsets/not_primary_errors_returned_if_client_sends_helloOk.js|80 col 1| assert(res.errmsg.includes("not primary"), res); jstests/replsets/not_primary_errors_returned_if_client_sends_helloOk.js|81 col 1| assert(!res.errmsg.includes("not master"), res); jstests/replsets/reconfig_fails_no_cwwc_set.js|29 col 1| assert(res.errmsg.includes(reconfigErrorMsg)); jstests/replsets/reconfig_fails_no_cwwc_set.js|34 col 1| assert(res.errmsg.includes(reconfigErrorMsg)); jstests/replsets/rollback_aborted_prepared_transaction.js|68 col 1| assert(res.errmsg.includes("cannot be run before its prepare oplog entry has been majority committed"), res); jstests/replsets/rslib.js|263 col 17| assert(res.errmsg.includes(errMsg)); jstests/replsets/split_horizon/split_horizon_hostname_startup.js|67 col 1| assert(output.errmsg.includes("Found split horizon configuration using IP")); jstests/replsets/txn_override_unittests.js|52 col 5| assert(!runCommandOverrideDenylistedCommands.includes(cmdName)); jstests/replsets/txn_override_unittests.js|61 col 5| assert(!runCommandOverrideDenylistedCommands.includes(cmdName)); jstests/replsets/txn_override_unittests.js|78 col 5| assert(!runCommandOverrideDenylistedCommands.includes(cmdName)); jstests/replsets/txn_override_unittests.js|88 col 5| assert(!runCommandOverrideDenylistedCommands.includes(cmdName)); jstests/replsets/txn_override_unittests.js|98 col 5| assert(!runCommandOverrideDenylistedCommands.includes(cmdName)); jstests/replsets/txn_override_unittests.js|119 col 5| assert(!runCommandOverrideDenylistedCommands.includes(cmdName)); jstests/replsets/txn_override_unittests.js|136 col 5| assert(!runCommandOverrideDenylistedCommands.includes(cmdName));
Replacing this with assert.includes greatly improves debuggability, since assert.includes will actually output the value of the haystack and needle, instead of just "assert failed":
const arr = [...Array.from({ length: 16 }).keys()].map(i => (i * i) % 11) try { assert(arr.includes(10)); } catch (e) { jsTest.log(e); } try { assert.includes(arr, 10); } catch (e) { jsTest.log(e); } /** * * * [jsTest] ---- * [jsTest] new Error("assert failed") * [jsTest] ---- * * { ... } * * [jsTest] ---- * [jsTest] new Error("string [[ 0, 1, 4, 9, 5, 3, 3, 5, 9, 4, 1, 0, 1, 4, 9, 5 ]] does not include [10]") * [jsTest] ---- * */