medusa icon indicating copy to clipboard operation
medusa copied to clipboard

[Bug]: Update Product Variant Hook throws error yet the data is persisted

Open juanzgc opened this issue 6 months ago • 2 comments

Package.json file

"dependencies": {
    "@medusajs/admin-sdk": "2.7.1",
    "@medusajs/cli": "2.7.1",
    "@medusajs/framework": "2.7.1",
    "@medusajs/medusa": "2.7.1",
    "@mikro-orm/core": "6.4.3",
    "@mikro-orm/knex": "6.4.3",
    "@mikro-orm/migrations": "6.4.3",
    "@mikro-orm/postgresql": "6.4.3",
    "awilix": "^8.0.1",
    "luxon": "^3.6.0",
    "pg": "^8.13.0"
  },
  "devDependencies": {
    "@medusajs/test-utils": "2.7.1",
    "@mikro-orm/cli": "6.4.3",
    "@swc/core": "1.5.7",
    "@swc/jest": "^0.2.36",
    "@types/jest": "^29.5.13",
    "@types/luxon": "^3",
    "@types/node": "^20.0.0",
    "@types/react": "^18.3.2",
    "@types/react-dom": "^18.2.25",
    "jest": "^29.7.0",
    "prop-types": "^15.8.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "ts-node": "^10.9.2",
    "typescript": "^5.6.2",
    "vite": "^5.2.11",
    "yalc": "^1.0.0-pre.53"
  },

Node.js version

v20.3.0

Database and its version

PostgreSQL 16.2

Operating system name and version

Mac Sonoma 14.0

Browser name

Chrome

What happended?

updateProductVariantsWorkflow.hooks.productVariantsUpdated upon throwing an error within the hook the update variant POST api returns a 400 status (as expected), however the updated data is persisted (not expected).

Expected behavior

Upon an error being thrown, one would expect the data to not be persisted.

Actual behavior

Steps to Reproduce: Create a Product Variants Updated hook and throw an error. The data should not be updated once the error is thrown.

Hook in question productVariantsUpdated:

updateProductVariantsWorkflow.hooks.productVariantsUpdated(
  async ({ product_variants }, { container }) => {
    const productModuleService = container.resolve("product");

    await Promise.all(
      product_variants.map(async (variant) => {
        const product = await productModuleService.retrieveProduct(
          variant.product_id as string
        );
        // Check if the product is marked as rental
        if (product.metadata?.is_rental) {
          // Don't allow inventory management to be enabled on variants of a rental product
          if (variant.manage_inventory === true) {
            throw new MedusaError(
              MedusaError.Types.NOT_ALLOWED,
              `Cannot enable Manage Inventory on variants with a rental product.`
            );
          }
        }
      })
    );
  }
);

In this case the error is thrown and seen in the logs:

error:   Cannot enable Manage Inventory on variants with a rental product.
{
  message: 'Cannot enable Manage Inventory on variants with a rental product.',
  name: 'Error',
  stack: 'Error: Cannot enable Manage Inventory on variants with a rental product.\n' +
    '    at /Users/juan/livelo/livelo-global-server/src/workflows/hooks/product-variant-updated.ts:17:19\n' +
    '    at processTicksAndRejections (node:internal/process/task_queues:95:5)\n' +
    '    at async Promise.all (index 0)\n' +
    '    at async Object.<anonymous> (/Users/juan/livelo/livelo-global-server/src/workflows/hooks/product-variant-updated.ts:8:5)\n' +
    '    at async Object.invoke (/Users/juan/livelo/livelo-global-server/node_modules/@medusajs/workflows-sdk/src/utils/composer/helpers/create-step-handler.ts:79:52)\n' +
    '    at async DistributedTransaction.handler (/Users/juan/livelo/livelo-global-server/node_modules/@medusajs/orchestration/src/workflow/workflow-manager.ts:214:16)\n' +
    '    at async stepHandler (/Users/juan/livelo/livelo-global-server/node_modules/@medusajs/orchestration/src/transaction/transaction-orchestrator.ts:984:14)\n' +
    '    at async Promise.allSettled (index 0)\n' +
    '    at async promiseAll (/Users/juan/livelo/livelo-global-server/node_modules/@medusajs/utils/src/common/promise-all.ts:27:18)\n' +
    '    at async TransactionOrchestrator.executeNext (/Users/juan/livelo/livelo-global-server/node_modules/@medusajs/orchestration/src/transaction/transaction-orchestrator.ts:838:7)\n' +
    '⮑ sat /Users/juan/livelo/livelo-global-server/node_modules/@medusajs/core-flows/dist/product/workflows/update-product-variants.js: [update-product-variants -> productVariantsUpdated (invoke)]',
  __isMedusaError: true,
  type: 'not_allowed',
  code: undefined,
  date: 2025-05-06T01:27:13.624Z
}
http:    POST /admin/products/prod_01JK26R5K6PF14X128EC0CB365/variants/variant_01JK26R5NTAPM82S6V8GSZBMH8 ← http://localhost:9000/app/products/prod_01JK26R5K6PF14X128EC0CB365/variants/variant_01JK26R5NTAPM82S6V8GSZBMH8/edit (400) - 138.140 ms

However, the product variant's data is still updated. Seems to be a faulty logic within the workflow / hook.

Link to reproduction repo

Steps to reproduce above

juanzgc avatar May 06 '25 01:05 juanzgc