What is Causing an Axios Error in a Node.js Action?

This topic was automatically generated from Slack. You can find the original thread here.

Hi guys,

I’m running a node.js action. However I am running into an axios error:

at Function.AxiosError.from (file:///tmp/pdg/dist/code/0cdb249fab1ab952d609fef700c4441b4e4b3376ef97519218865ce5456ff8b5/node_modules/.pnpm/axios@1.2.1/node_modules/axios/lib/core/AxiosError.js:89:14)
at BrotliDecompress.handleStreamError (file:///tmp/pdg/dist/code/0cdb249fab1ab952d609fef700c4441b4e4b3376ef97519218865ce5456ff8b5/node_modules/.pnpm/axios@1.2.1/node_modules/axios/lib/adapters/http.js:489:29)
at BrotliDecompress.emit (events.js:412:35)
at null.emitErrorNT (internal/streams/destroy.js:106:8)
at null.emitErrorCloseNT (internal/streams/destroy.js:74:3)
at process.processTicksAndRejections (internal/process/task_queues.js:82:21)

code: ‘Z_BUF_ERROR’,
errno: -5,
message: ‘unexpected end of file’,

My request is atteched in the image.

I have run the request in Postman however I dont face the same issue there.
I only added the timeout for tests reason.

Can someone help me with this?

Thanks <3

This is how i require axios

image.png

Have you tested this API call with a Postman or Insomnia like tool to make sure the API isn’t returning this error?

Can you share the entire code step’s contents?

I tested with postman and that works fine

I can give you the code however you would be missing the API Keys

Would that help?

Yes, that works. We are only be checking the format of the code

import axios from ‘axios’

export default {
name: “Get Tracking from PN”,
description: “Get Tracking from PN”,
key: “getTrackingFromPN”,
version: “0.0.14”,
type: “action”,
props: {
orders: {
type: “object”,
label: “Orders”
},
location_id: {
type: “string”,
label: “Location Id”
},
store: {
type: “string”,
label: “Shopify Store URL”
},
store_key: {
type: “string”,
label: “Shopify Auth Key”
},
pn_key: {
type: “string”,
label: “Picanova Auth Key”
},
},
async run({$}) {

    await synrchoniseOrders(this.orders, this.location_id, this.store, this.store_key, [this.pn](http://this.pn)_key);


    async function synrchoniseOrders(orders, location_id, store, store_key, pn_key) {
        for(var i in orders) {
            var shOrder = orders[i];
            var ids = getPicaIds(shOrder.tags);
            console.log(ids);

            for(var j in ids) {

                await getPicaOrder(ids[j].trim(), pn_key)
                    .then(async (picaOrder) =&gt; {

                        await fulfillOrder(picaOrder, location_id, store);

                    })
                    .catch((err) =&gt; {
                        console.log("uncaught error whilst getting pn order: "+ids[j]);
                        console.log(typeof err.response !== "undefined" ? err.response.data : err);
                    });

            }

        }

    }

    function getPicaIds(tags) {
        var tagsArr = tags.split(',');
        var ids = [];
        for(var i in tagsArr)
            if(tagsArr[i].indexOf('PPO') !== -1)
                ids.push(tagsArr[i]);

        return ids;
    }

    async function getPicaOrder(id, pn_key) {
        var result;
        const endpoint = "https://api.picanova.com/api/beta/orders/"+id;

        await axios.get(endpoint, { headers: { 'Authorization': 'Basic ' + pn_key }} )
            .then((res) =&gt; {
                console.log("Order with id "+id+" fetched from Picanova");
                result = res.data.data;
            })
            .catch((err) =&gt; {
                console.log("Error whilst getting order with id " +id+ " from PN");
                console.log(typeof err.response !== "undefined" ? err.response.data : err);
            });
        return result;
    }

    async function fulfillOrder(picaOrder, id, location_id, store) {
        const endpoint    = "https://"+store+".[myshopify.com/admin/api/2022-04/orders/](http://myshopify.com/admin/api/2022-04/orders/)" + id + "/fulfillments.json";
        const fulfillment =  getFulfillment(picaOrder, location_id);
        console.log(JSON.stringify(fulfillment));
    }

    function getFulfillment(picaOrder, location_id) {
        return {
            "fulfillment": {
            "location_id": location_id,
            "tracking_company": "",
            "tracking_number": "",
            "tracking_urls": getTrackingUrls(picaOrder),
            "line_items": getItemIds(picaOrder),
            "notify_customer": false
            }
          }
    }

    function getTrackingUrls(picaOrder) {
        var shipments = picaOrder.shipments;
        var urls = [];
        for(var i in shipments)
            urls.push(shipments[i].tracking_url);
        return urls;
    }

    function getItemIds(picaOrder) {
        var items = picaOrder.items;
        var ids = [];

        for(var i in items) {
            if(items[i].external_id) {
                ids.push({ "id": items[i].external_id });
            } else {
                console.log("Manual Order deteced");
            }
        }
        return ids;
    }
}

}

First thing I notice is that your for loop isn’t going to be awaited for properly

The workflow isn’t waiting for your loop to finish before it moves on to the next step in your workflow

You can either use Promise.all to await an array of promises all sent at once, or you can use for await (item of items) to await each promise consecutively.

Oh thanks for the input

I wasnt await that await in a loop would cause issues

do i need both awaits?

Correct, you’ll need to await all Promises in order for the step to function properly.

Here’s a specific section in our docs about it: Running asynchronous code in Node.js

There’s quite a bit of API calls going on in one step, I would personally split these into individual actions, it’ll be much easier to diagnose which call is causing issues.

The issue i have with that is that each would cause an invocation ergo make the cronjob conciderably more expensive.

I would love to refactor my code in such a way but I have to keep invocations in mind

Also, I can’t call actions from code or loop themn

You can still use an unlimited number of steps in one workflow, so it wouldn’t cost any additional invocations to split one action into many, if that helps.