If I create an RBF transaction using the Qt GUI but specify my own custom change address, bumpfee doesn't work because it claims it can't find the change address:

    "Transaction does not have a change output"

This is because none of the outputs satisfy

    pWallet->IsChange(...)

I see there's a "TODO" commented in `CWallet::IsChange()` in `src/wallet/wallet.cpp`:

    // TODO: fix handling of 'change' outputs. The assumption is that any
    // payment to a script that is ours, but is not in the address book
    // is change.

I tend to put all my addresses in the address book whether I'm going to use them as change or not. I guess if the wallet was capable of creating its own SegWit change addresses I'd stop using custom change addresses, but currently it always seems to send change to a legacy address if I don't manually specify a change address.
const std::string& desc_str  = desc_univ.get_str();
                FlatSigningProvider desc_out;
                std::string error;
                std::vector<CScript> scripts_temp;
                std::unique_ptr<Descriptor> desc = Parse(desc_str, desc_out, error, true);
                if (!desc) {
                    throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Unable to parse descriptor '%s': %s", desc_str, error));
                }
                desc->Expand(0, desc_out, scripts_temp, desc_out);
                coinControl.m_external_provider.Merge(std::move(desc_out));
            }
        }
    }
    if (options.exists("input_weights")) {
        for (const UniValue& input : options["input_weights"].get_array().getValues()) {
            uint256 txid = ParseHashO(input, "txid");
            const UniValue& vout_v = input.find_value("vout");
            if (!vout_v.isNum()) {
                throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
            }
            int vout = vout_v.getInt<int>();
            if (vout < 0) {
                throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout cannot be negative");
            }
            const UniValue& weight_v = input.find_value("weight");
            if (!weight_v.isNum()) {
                throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing weight key");
            }
            int64_t weight = weight_v.getInt<int64_t>();
            const int64_t min_input_weight = GetTransactionInputWeight(CTxIn());