stripe-node icon indicating copy to clipboard operation
stripe-node copied to clipboard

products.list throws error when ids array is larger than default limit value (10)

Open rconjaerts opened this issue 3 years ago • 7 comments

Describe the bug

When you try to retrieve a list of products via the products.list() function, and you add an ids parameter whose array size is larger than the default limit value (10), Stripe will throw an StripeInvalidRequestError. The message and param of the error is the following:

message: 'You may only specify one of these parameters: ids, starting_after.', param: 'ids',

To Reproduce

  1. Fetch list of products and add an array of ids larger than 10 elements

Expected behavior

The length of the array of ids shouldn't be constrained by the limit parameter

Code snippets

No response

OS

macOS

Node version

v16.13.2

Library version

stripe v9.6.0

API version

2020-08-27

Additional context

No response

rconjaerts avatar Jul 01 '22 12:07 rconjaerts

@rconjaerts Could you give a bit more details and an exact reproduction? I tried the following code which works fine whether I pass a limit set to 1, 5 or 10.

var products = await stripe.products.list({
  ids: ['1', '2', '3', '4','5','6','7','8','9','10', '11', '12'],
})

I tried with various alternatives, with and without more than 10 real product ids and couldn't reproduce.

remi-stripe avatar Jul 01 '22 15:07 remi-stripe

My apologies for the late reply, I have to change my notification settings properly. It's weird that you don't seem to have this issue. Our complete function that we're using is the following.

export async function getProducts(
  stripeClient: Stripe,
  productIds: string[],
  entityId: string,
  integrationId: string
): Promise<ProductCreationAttributes[]> {
  const products = []
  for await (const product of stripeClient.products.list({ ids: productIds })) {
    products.push(mapProductToDb(product, entityId, integrationId))
  }
  return products
}

I've also added logs from our import service that threw the error:

2022-07-01T12:09:23.134Z stripe-subscription-import Starting importer 2022-07-01T12:09:23.859Z stripe-subscription-import Fetching subscriptions & subscription items 2022-07-01T12:09:28.126Z stripe-subscription-import Found 48 subscriptions 2022-07-01T12:09:28.128Z stripe-subscription-import Found 97 subscription items 2022-07-01T12:09:28.130Z stripe-subscription-import Upserting subscriptions 2022-07-01T12:09:28.144Z stripe-subscription-import Fetching products 2022-07-01T12:09:28.152Z stripe-subscription-import [ 'prod_XXXXXXXXXXXX', 'prod_XXXXXXXXXXXX', 'prod_XXXXXXXXXXXX', 'prod_XXXXXXXXXXXX', 'prod_XXXXXXXXXXXX', 'prod_XXXXXXXXXXXX', 'prod_XXXXXXXXXXXX', 'prod_XXXXXXXXXXXX', 'prod_XXXXXXXXXXXX', 'prod_XXXXXXXXXXXX', 'prod_XXXXXXXXXXXX', 'prod_XXXXXXXXXXXX', 'prod_XXXXXXXXXXXX' ] /app/node_modules/stripe/lib/Error.js:40 return new StripeInvalidRequestError(rawStripeError); ^

StripeInvalidRequestError: You may only specify one of these parameters: ids, starting_after. at Function.generate (/app/node_modules/stripe/lib/Error.js:40:16) at res.toJSON.then.StripeAPIError.message (/app/node_modules/stripe/lib/StripeResource.js:226:35) at processTicksAndRejections (node:internal/process/task_queues:96:5) { type: 'StripeInvalidRequestError',

Note that in logs in the array of products, I removed the actual ids and replaced it by XXXXXXXXXXXX as a security measure. If I add limit: 100 to the options, the error isn't thrown.

rconjaerts avatar Jul 11 '22 12:07 rconjaerts

@rconjaerts Can I ask you to provide an exact script to simply reproduce the exact issue end to end? Your function help but if you could share exact end to end code that would make things a lot easier.

remi-stripe avatar Jul 11 '22 16:07 remi-stripe

Sure, I ran this with ts-node and after 10 product logs it failed. When I set the limit option higher than 10, it works.

import { Stripe } from "stripe"

const apikey = '';
// list of 13 productIds
const productIds = [];
async function main() {
  const stripeClient = new Stripe(apikey, { apiVersion: '2020-08-27' });
  // console.log() works for 10 products and error is thrown for the 11th. It does work however if we add the limit option
  for await (const product of stripeClient.products.list({ ids: productIds })) {
    console.log(product)
  }
}

main();

rconjaerts avatar Jul 12 '22 06:07 rconjaerts

Thanks, I was able to reproduce after tweaking that code. It seems we don't support getting to the next page in this case but don't document it. We'll investigate whether this is a real bug we need to fix or more a feature request we hadn't encountered before. Tagging as future for now but I'm definitely surprised by this behaviour.

remi-stripe avatar Jul 12 '22 14:07 remi-stripe

Quick fix would also be to allow a higher limit value. Currently the maximum value is 100, but I can imagine that some of our clients might have more than 100 unique products.

rconjaerts avatar Jul 12 '22 15:07 rconjaerts

We would never allow the limit higher than 100 so that won't be a potential solution. You mostly need to split your list in smaller chunks or cache this in your database instead.

remi-stripe avatar Jul 12 '22 18:07 remi-stripe