BSONObj getErrorLabels(const OperationSessionInfoFromClient& sessionOptions,
                       const std::string& commandName,
                       ErrorCodes::Error code,
                       bool hasWriteConcernError) {
    BSONArrayBuilder labelArray;

    // Note that we only apply the TransientTxnError label if the "autocommit" field is present in
    // the session options. When present, "autocommit" will always be false, so we don't check its
    // value.
    if (sessionOptions.getAutocommit() &&
        isTransientTransactionError(code,
                                    hasWriteConcernError,
                                    commandName == "commitTransaction" ||
                                        commandName == "coordinateCommitTransaction")) {
        // An error code for which isTransientTransactionError() is true indicates a transaction
        // failure with no persistent side effects.
        labelArray << txn::TransientTxnErrorFieldName;
    }

    if (ErrorCodes::isNonResumableChangeStreamError(code)) {
        labelArray << "NonResumableChangeStreamError";
    }

    return (labelArray.arrSize() > 0) ? BSON("errorLabels" << labelArray.arr()) : BSONObj();
}
void validateSessionOptions(const OperationSessionInfoFromClient& sessionOptions,
                            StringData cmdName,
                            StringData dbname) {
    if (sessionOptions.getAutocommit()) {
        uassertStatusOK(CommandHelpers::canUseTransactions(dbname, cmdName));
    }

    if (sessionOptions.getTxnNumber()) {
        uassert(50768,
                str::stream() << "It is illegal to provide a txnNumber for command " << cmdName,
                commandCanCheckOutSession(cmdName) || shouldCommandSkipSessionCheckout(cmdName));
    }

    if (sessionOptions.getStartTransaction()) {
        uassert(ErrorCodes::OperationNotSupportedInTransaction,
                "Cannot run killCursors as the first operation in a multi-document transaction.",
                cmdName != "killCursors");
    }
}