Stack Exchange
Hyperledger fabric client ENDORSEMENT_POLICY_FAILURE
While connecting first network (byfn) to node client with fabric-client package I'm getting below error
code : https://pastebin.com/SFEVXXvM
`
'use strict';
/*
* Copyright IBM Corp All Rights Reserved
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
 * Chaincode Invoke
 */

var Fabric_Client = require('fabric-client');
var path = require('path');
var util = require('util');
var os = require('os');
var fs = require('fs');
//
var fabric_client = new Fabric_Client();

// setup the fabric network
var channel = fabric_client.newChannel('mychannel');

const peer_tls = "../network/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt";
const peer_tls_data = fs.readFileSync(path.join(__dirname, peer_tls));

var peer = fabric_client.newPeer('grpcs://localhost:7051',{
    pem : Buffer.from(peer_tls_data).toString(),
    'ssl-target-name-override' : "peer0.org1.example.com"
});
channel.addPeer(peer);

const orderer_tls = "../network/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt";
const orderer_tls_data = fs.readFileSync(path.join(__dirname, orderer_tls));
var order = fabric_client.newOrderer('grpcs://localhost:7050',{
    pem : Buffer.from(orderer_tls_data).toString(),
    'ssl-target-name-override' : "orderer.example.com"
})

channel.addOrderer(order);

//
var member_user = null;
var store_path = path.join(__dirname, 'hfc-key-store');
console.log('Store path:'+store_path);
var tx_id = null;

// create the key value store as defined in the fabric-client/config/default.json 'key-value-store' setting
Fabric_Client.newDefaultKeyValueStore({ path: store_path
}).then((state_store) => {
    // assign the store to the fabric client
    fabric_client.setStateStore(state_store);
    var crypto_suite = Fabric_Client.newCryptoSuite();
    // use the same location for the state store (where the users' certificate are kept)
    // and the crypto store (where the users' keys are kept)
    var crypto_store = Fabric_Client.newCryptoKeyStore({path: store_path});
    crypto_suite.setCryptoKeyStore(crypto_store);
    fabric_client.setCryptoSuite(crypto_suite);

    // get the enrolled user from persistence, this user will sign all requests
    return fabric_client.getUserContext('user2', true);
}).then((user_from_store) => {
    if (user_from_store && user_from_store.isEnrolled()) {
        console.log('Successfully loaded user2 from persistence');
        member_user = user_from_store;
    } else {
        throw new Error('Failed to get user2.... run registerUser.js');
    }

    // get a transaction id object based on the current user assigned to fabric client
    tx_id = fabric_client.newTransactionID();
    console.log("Assigning transaction_id: ", tx_id._transaction_id);

    // createCar chaincode function - requires 5 args, ex: args: ['CAR12', 'Honda', 'Accord', 'Black', 'Tom'],
    // changeCarOwner chaincode function - requires 2 args , ex: args: ['CAR10', 'Dave'],
    // must send the proposal to endorsing peers
    var request = {
        //targets: let default to the peer assigned to the client
        chaincodeId: 'mycc',
        fcn: 'post',
        args: [JSON.stringify(
            {
                "Taxable": "false",
                "BillAddr": {
                  "Id": "16",
                  "Line1": "789 Sugar Lane",
                  "City": "Middlefield",
                  "CountrySubDivisionCode": "CA",
                  "PostalCode": "94303",
                  "Lat": "37.4530553",
                  "Long": "-122.1178261"
                },
                "Job": "false",
                "BillWithParent": "false",
                "Balance": "75",
                "BalanceWithJobs": "75",
                "CurrencyRef": {
                  "value": "USD",
                  "name": "United States Dollar"
                },
                "PreferredDeliveryMethod": "Print",
                "Id": "16",
                "MetaData": {
                  "CreateTime": "2021-09-12T17:11:27-07:00",
                  "LastUpdatedTime": "2021-09-18T15:18:18-07:00"
                },
                "GivenName": "Kathy",
                "FamilyName": "Kuplis",
                "FullyQualifiedName": "Kookies by Kathy",
                "CompanyName": "Kookies by Kathy",
                "DisplayName": "Kookies by Kathy",
                "PrintOnCheckName": "Kookies by Kathy",
                "Active": "true",
                "PrimaryPhone": {
                  "FreeFormNumber": "(650) 555-7896"
                },
                "PrimaryEmailAddr": {
                  "Address": "qbwebsamplecompany@yahoo.com"
                }
              }
        ), "Customer", "16"],
        chainId: 'mychannel',
        txId: tx_id
    };
    
    // send the transaction proposal to the peers
    return channel.sendTransactionProposal(request);
}).then((results) => {
    var proposalResponses = results[0];
    var proposal = results[1];
    let isProposalGood = false;
    if (proposalResponses && proposalResponses[0].response &&
        proposalResponses[0].response.status === 200) {
            isProposalGood = true;
            console.log('Transaction proposal was good');
        } else {
            console.error('Transaction proposal was bad');
        }
    if (isProposalGood) {
        console.log(util.format(
            'Successfully sent Proposal and received ProposalResponse: Status - %s, message - "%s"',
            proposalResponses[0].response.status, proposalResponses[0].response.message));

        // build up the request for the orderer to have the transaction committed
        var request = {
            proposalResponses: proposalResponses,
            proposal: proposal
        };

        // set the transaction listener and set a timeout of 30 sec
        // if the transaction did not get committed within the timeout period,
        // report a TIMEOUT status
        var transaction_id_string = tx_id.getTransactionID(); //Get the transaction ID string to be used by the event processing
        var promises = [];

        var sendPromise = channel.sendTransaction(request);
        promises.push(sendPromise); //we want the send transaction first, so that we know where to check status

        // get an eventhub once the fabric client has a user assigned. The user
        // is required bacause the event registration must be signed
        let event_hub = channel.newChannelEventHub(peer);

        // using resolve the promise so that result status may be processed
        // under the then clause rather than having the catch clause process
        // the status
        let txPromise = new Promise((resolve, reject) => {
            let handle = setTimeout(() => {
                event_hub.unregisterTxEvent(transaction_id_string);
                event_hub.disconnect();
                resolve({event_status : 'TIMEOUT'}); //we could use reject(new Error('Trnasaction did not complete within 30 seconds'));
            }, 3000);
            event_hub.registerTxEvent(transaction_id_string, (tx, code) => {
                // this is the callback for transaction event status
                // first some clean up of event listener
                clearTimeout(handle);

                // now let the application know what happened
                var return_status = {event_status : code, tx_id : transaction_id_string};
                if (code !== 'VALID') {
                    console.error('The transaction was invalid, code = ' + code);
                    resolve(return_status); // we could use reject(new Error('Problem with the tranaction, event status ::'+code));
                } else {
                    console.log('The transaction has been committed on peer ' + event_hub.getPeerAddr());
                    resolve(return_status);
                }
            }, (err) => {
                //this is the callback if something goes wrong with the event registration or processing
                reject(new Error('There was a problem with the eventhub ::'+err));
            },
                {disconnect: true} //disconnect when complete
            );
            event_hub.connect();

        });
        promises.push(txPromise);

        return Promise.all(promises);
    } else {
        console.error('Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...');
        throw new Error('Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...');
    }
}).then((results) => {
    console.log('Send transaction promise and event listener promise have completed');
    // check the results in the order the promises were added to the promise all list
    if (results && results[0] && results[0].status === 'SUCCESS') {
        console.log('Successfully sent transaction to the orderer.');
    } else {
        console.error('Failed to order the transaction. Error code: ' + results[0].status);
    }

    if(results && results[1] && results[1].event_status === 'VALID') {
        console.log('Successfully committed the change to the ledger by the peer');
    } else {
        console.log('Transaction failed to be committed to the ledger due to ::'+results[1].event_status);
    }
}).catch((err) => {
    console.error('Failed to invoke successfully :: ' + err);
});


function marshalArgs(args) {
    if (!args) {
        return args;
    }

    if (typeof args === 'string') {
        return [args];
    }

    //let snakeArgs = converter.camelToSnakeCase(args);

    if (Array.isArray(args)) {
        arr = [];
        for(i=0;i<args.length;i++){
            let arg = marshalArgs(args[i]);
            arr.push(arg);
        }
        return arr;
    }

    if (typeof args === 'object') {
        return [JSON.stringify(objToString(args))];
    }
}
/*
 * Convert all the properties of a object to String 
 */  

function objToString(myObj){
    Object.keys(myObj).forEach(function(key){
      typeof myObj[key] == 'object' ? objToString(myObj[key]) : myObj[key]= String(myObj[key]);
    });
    return myObj;
}

`

Assigning transaction_id:  ea8291e609e66b5a2312cce32e432dcc661e09109876e5dea692a12dd6f95b62
Transaction proposal was good
Successfully sent Proposal and received ProposalResponse: Status - 200, message - ""
The transaction was invalid, code = ENDORSEMENT_POLICY_FAILURE
Send transaction promise and event listener promise have completed
Successfully sent transaction to the orderer.
Transaction failed to be committed to the ledger due to ::ENDORSEMENT_POLICY_FAILURE


This likely occurred because when you need multiple peers from different orgs to have the transaction be sent to, the endorsement policy is AND. 
You can set request's target to all the peers specified in the endorsement policy and that should fix this
