gocardless-nodejs icon indicating copy to clipboard operation
gocardless-nodejs copied to clipboard

RequestError with ERR_INVALID_ARG_TYPE

Open ghost opened this issue 5 years ago • 11 comments

Hello,

I have (in a production environment only) this kind of error that happens randomly when I try call some methods of the library (using the 1.1.2 version) like the following:

      const mandate = await client.mandates.find(mandateId);

      const { account_number_ending: bankAccountNumberEnding } = await client.customerBankAccounts.find(
        mandate.links.customer_bank_account,
      );

OR

      const { url } = await client.mandatePdfs.create(
        {
          links: {
            mandate: mandateId,
          },
        },
        '',
        {
          'Accept-Language': language || 'en',
        },
      );

The error:

"extensions": {
  "name": "RequestError",
  "code": "GOCARDLESS_ERROR",
  "exception": {
    "name": "RequestError",
    "code": "ERR_INVALID_ARG_TYPE"
  }
}

GOCARDLESS_ERROR is an internal error name, but RequestError and ERR_INVALID_ARG_TYPE are returned by GoCardless.

Do you know where this could come from? It sometimes works like a charm, but then I will have this error.

ghost avatar May 13 '20 14:05 ghost

Hey @RomainCscnLF, apologies for getting back so late.

I've attempted to replicate this behaviour, but no luck. I've got a few follow-up questions to help me get further with this:

Just to be clear, does this only happens in the production environment? Does this happen on all endpoints and method types, or only some?

tallosan avatar May 20 '20 11:05 tallosan

My guess at this point is that it's something related to the logic you're using when populating the request parameters, and the way we then handle these invalid requests.

For example, in the mandatePdfs.create call, the language value in the Accept-Language header might, on occasion, get set incorrectly. Then, rather than return a helpful error message telling you what went wrong, we might just return a generic INVALID_ARG_TYPE one. Presumably this only comes about when language is set to something that we aren't parsing correctly on our end.

I can't replicate this behaviour on my end, but I'm curious as to whether you've explored this possibility.

tallosan avatar May 20 '20 11:05 tallosan

Just to be clear, does this only happens in the production environment? Does this happen on all endpoints and method types, or only some?

I tested to replicate this in my dev environment but could not. So I can confirm it is only in my production environment.

It happens on all endpoints (not only mandatePdfs.create). So I don't think it could come from the Accept-Language header.

So even with this simple call const mandate = await client.mandates.find(mandateId); where I'm sure that there is a mandateId, it sometimes happened.

ghost avatar May 20 '20 11:05 ghost

Hmm, are there any key differences between your production and staging environment?

We recently had an issue where an integrator had a similar issue with their integration working fine locally, but not in production.

I'm wondering if something similar is happening in your case.

tallosan avatar May 22 '20 12:05 tallosan

I don't know enough about the key differences between production and dev environment. I'll check with some of my colleagues.

That probably is something similar.

ghost avatar May 25 '20 13:05 ghost

Hi again @tallosan ,

Could it be that some headers are missing from the call depending on the environment?

ghost avatar Jun 08 '20 12:06 ghost

I traced down the error by adding some logs, our config looks good.

I'm now sure that I'm getting the error when I'm calling this method:

const mandate = await client.mandates.find(mandateId);

I assured myself that mandateId is a string by logging is type before with this:

logger.info({ mandateIdType: typeof mandateId }, 'MANDATE ID type');

And that returns string. I don't really know what to do next.

But I catch the following error:

{
  "code": "ERR_INVALID_ARG_TYPE",
  "name": "RequestError"
}

happening randomly.

(ps: I'm using 1.2.0 now)

ghost avatar Jun 09 '20 10:06 ghost

Hi again @tallosan ,

Could it be that some headers are missing from the call depending on the environment?

The missing headers should give you a different error, so I think it's unlikely. I'll look into it though.

Just to be clear, are you saying that the error only happens on this particular method (mandates.find)?

I'll see what I can do, but this kind of issue is quite difficult to resolve given the lack of visibility (and rightly so) that we have into your setup. Narrowing this down to one method should help, but unless I'm able to replicate this behaviour I'll still be a bit in the dark.

tallosan avatar Jun 09 '20 17:06 tallosan

Just to be clear, are you saying that the error only happens on this particular method (mandates.find)?

Unfortunately, it doesn't seem related to this method in particular. The issue also happens on mandatePdfs.create and mandates.create.

It looks like an error isn't caught properly. I looked at the code, could it come from the method request? It's the only place where there is a try/catch. And there is an error code so I'm thinking that it is caught but there is nothing more?

ghost avatar Jun 09 '20 17:06 ghost

Hello again @tallosan.

I rewrote the queries we had using http calls directly, and we're not facing errors anymore. So it looks like it definitely is something on the gocardless-nodejs lib.

FYI, we're using AWS on our prod env.

ghost avatar Jun 15 '20 07:06 ghost

Hey @RomainCscnLF, I'm following up on @tallosan's investigation.

Apparently, the RequestError error is coming from Got, the HTTP client we're using under the hood to interact with our API. As for ERR_INVALID_ARG_TYPE, it's a Node.js error code.

In other words, I think the original error is thrown by one of the Node.js APIs and is wrapped by Got in a custom RequestError. Later on, we catch this error in our request method (as you rightfully pointed out in your previous comment) and re-throw it here.

To move forward, we'd need to have more information on the original error. A stack trace could be very helpful in that regard.

You should be able to recover a stack trace using the stack property of the error object:

try {
  await client.mandates.find(mandateId)
} catch (e) {
  console.log(e.stack)
}

Could you communicate that back to us?

In addition, could you please share:

  • The version of Node.js you're using in production?
  • The version of Got that was installed alongside our client library? (You should be able to retrieve this information with npm list got.)

matthieuprat avatar Jun 17 '20 05:06 matthieuprat