{"record":{"id":"1b4441fba639f972","repo":"medusajs/medusa","slug":"cart-cart-id-already-has-a-payment-collection","errorCode":null,"errorMessage":"Cart ${cart.id} already has a payment collection","messagePattern":"Cart (.+?) already has a payment collection","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/core-flows/src/cart/workflows/create-payment-collection-for-cart.ts","lineNumber":56,"sourceCode":" *\n * :::\n *\n * @example\n * const data = validateExistingPaymentCollectionStep({\n *   cart: {\n *     // other cart details...\n *     payment_collection: {\n *       id: \"paycol_123\",\n *       // other payment collection details.\n *     }\n *   }\n * })\n */\nexport const validateExistingPaymentCollectionStep = createStep(\n  \"validate-existing-payment-collection\",\n  ({ cart }: ValidateExistingPaymentCollectionStepInput) => {\n    if (cart.payment_collection) {\n      throw new Error(`Cart ${cart.id} already has a payment collection`)\n    }\n  }\n)\n\nexport const createPaymentCollectionForCartWorkflowId =\n  \"create-payment-collection-for-cart\"\n/**\n * This workflow creates a payment collection for a cart. It's executed by the\n * [Create Payment Collection Store API Route](https://docs.medusajs.com/api/store/payment-collections/create-payment-collection).\n *\n * You can use this workflow within your own customizations or custom workflows, allowing you to wrap custom logic around adding creating a payment collection for a cart.\n *\n * @example\n * const { result } = await createPaymentCollectionForCartWorkflow(container)\n * .run({\n *   input: {\n *     cart_id: \"cart_123\",\n *     metadata: {","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/core/core-flows/src/cart/workflows/create-payment-collection-for-cart.ts#L38-L74","documentation":"createPaymentCollectionForCartWorkflow guards against duplicates: if the cart already has an attached payment_collection, the validation step throws a plain Error (not a MedusaError) instead of creating a second collection.","triggerScenarios":"Calling createPaymentCollectionForCart for a cart that already went through payment creation — e.g. re-entering checkout, retrying after a network error, or calling the workflow twice in a flow without checking prior state.","commonSituations":"Storefront checkout resumed after refresh/retry; parallel requests (double click on 'Pay'); custom flows that assume the workflow is idempotent when it is not.","solutions":["Check cart.payment_collection before calling the workflow; reuse the existing collection if present","Make the client idempotent: guard double-submits before firing the request","If the stale collection is unwanted, delete it (or reset payment sessions) before creating a new one"],"exampleFix":"// before\nawait createPaymentCollectionForCartWorkflow(container).run({ input: { cart_id } })\n\n// after\nconst cart = await query.graph({ entity: 'cart', filters: { id: cart_id }, fields: ['payment_collection.id'] })\nif (!cart.data[0].payment_collection) {\n  await createPaymentCollectionForCartWorkflow(container).run({ input: { cart_id } })\n}","handlingStrategy":"type-guard","validationCode":"const { data: [cart] } = await query.graph({ entity: 'cart', fields: ['payment_collection.id'], filters: { id: cart_id } })\nif (cart.payment_collection) {\n  return { payment_collection: cart.payment_collection }\n}","typeGuard":"const cartNeedsPaymentCollection = (cart: CartDTO) =>\n  cart.payment_collection == null","tryCatchPattern":"try {\n  await createPaymentCollectionForCartWorkflow(container).run({ input: { cart_id } })\n} catch (e) {\n  if (/already has a payment collection/.test(e.message)) {\n    // refetch cart and continue with the existing collection\n  }\n}","preventionTips":["Check cart.payment_collection before invoking the workflow","Disable the pay button after first click to prevent double submission","Model checkout steps as idempotent resumable operations"],"tags":["cart","payment","idempotency","checkout"],"backgroundTag":"duplicate-resource","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}