stripe / stripe-node

Node.js library for the Stripe API.
https://stripe.com
MIT License
3.88k stars 751 forks source link

Posting invalid usage crashes the app #1436

Closed alko89 closed 2 years ago

alko89 commented 2 years ago

Describe the bug

I'm using an error middleware filter to catch errors thrown inside Stripe library. Its been working great for all responses I've tested, except when creating a usage record, which crashes with error:

/home/alko/Development/IvanOnTech/Moralis/moralis-billing-coordinator/node_modules/stripe/lib/Error.js:41
        return new StripeInvalidRequestError(rawStripeError);
               ^
Error: Cannot create the usage record because the subscription has been canceled.
    at Function.generate (/home/alko/Development/IvanOnTech/Moralis/moralis-billing-coordinator/node_modules/stripe/lib/Error.js:41:16)
    at res.toJSON.then.StripeAPIError.message (/home/alko/Development/IvanOnTech/Moralis/moralis-billing-coordinator/node_modules/stripe/lib/StripeResource.js:220:35)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)

To Reproduce

Create a usage on a canceled subscription

Expected behavior

Error should be handled. For example querying a non existing customer the API responds with an error message from the api and a 404 status message.

{
    "name": "resource_missing",
    "message": "No such customer: 'cus_IkltNeoStCxpP4E'"
}

Code snippets

The error filter I've created:

import { ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common';
import { Response } from 'express';
import { StripeError } from 'stripe/lib/Error';

@Catch(StripeError)
export class StripeErrorFilter implements ExceptionFilter {
  catch(exception: StripeError, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();

    response.status(exception.statusCode).json({
      name: exception.code,
      message: exception.message,
    });
  }
}

OS

Linux

Node version

v18.2.0

Library version

8.219.0

API version

2020-08-27

Additional context

No response

dcr-stripe commented 2 years ago

Thanks for the report @alko89 .

I'm having a hard time reproducing this. I'm using Node 18 + 9.5.0 (I don't think anything has changed that would impact this between our versions). If I do the following with a similarly set up subscription item, I get:

  try {
    const usageRecord = await stripe.subscriptionItems.createUsageRecord(
      '<id>',
      {quantity: 100, timestamp: 1571252444}
    );
  } catch (e) {
    console.log(e instanceof StripeError); // true
    console.log(e.constructor.name); // StripeInvalidRequestError
    console.log(e.statusCode); // 400
    console.log(e.code); // undefined
    console.log(e.rawType); // invalid_request_error
    console.log(e.message); // Cannot create the usage record because the subscription has been canceled.
  }  

Similarly, if I try with a missing customer:

try {
    await stripe.customers.retrieve("cus_idontexist");
  } catch (e) {
    console.log(e instanceof StripeError); // true
    console.log(e.constructor.name); // StripeInvalidRequestError
    console.log(e.statusCode); // 404
    console.log(e.code); // resource_missing
    console.log(e.rawType); // invalid_request_error
    console.log(e.message); // No such customer: 'cus_idontexist'
  }  

Both of these look like valid errors, and I get similar results if using cURL [0]. The one caveat here is that the usage records failure doesn't have a code, only a type (accessible via rawType). Is it possible your filter depends on this somehow?


[0]: cURL examples

$ curl https://api.stripe.com/v1/subscription_items/<ID>/usage_records   -u <KEY>:   -d quantity=100   -d timestamp=1571252444
{
  "error": {
    "message": "Cannot create the usage record because the subscription has been canceled.",
    "type": "invalid_request_error"
  }
}

$ curl https://api.stripe.com/v1/subscription_items/idonotexist/usage_records   -u <KEY>:   -d quantity=100   -d timestamp=1571252444
{
  "error": {
    "code": "resource_missing",
    "doc_url": "https://stripe.com/docs/error-codes/resource-missing",
    "message": "No such subscription item: 'idonotexist'",
    "param": "subscription_item",
    "type": "invalid_request_error"
  }
}
dcr-stripe commented 2 years ago

Going to close this out, but please feel free to re-open if you're still experiencing this issue. Thank you!