Package.json file
Backend package generated with create-medusa-app@2.20.1 --version 2.20.1. All Medusa packages below are unmodified npm releases. The root workspace configuration and pnpm lockfile are included in the reproduction repository.
{
"name": "@dtc/backend",
"version": "0.0.1",
"description": "A starter for Medusa projects.",
"author": "Medusa (https://medusajs.com)",
"license": "MIT",
"keywords": [
"sqlite",
"postgres",
"typescript",
"ecommerce",
"headless",
"medusa"
],
"scripts": {
"build": "medusa build",
"start": "medusa start",
"dev": "medusa develop",
"lint": "medusa lint",
"test:integration:http": "jest --runInBand"
},
"dependencies": {
"@medusajs/admin-sdk": "2.20.1",
"@medusajs/admin-shared": "2.20.1",
"@medusajs/caching": "2.20.1",
"@medusajs/cli": "2.20.1",
"@medusajs/dashboard": "2.20.1",
"@medusajs/draft-order": "2.20.1",
"@medusajs/framework": "2.20.1",
"@medusajs/medusa": "2.20.1",
"@medusajs/ui": "4.2.3",
"@tanstack/react-query": "5.64.2",
"react-i18next": "13.5.0",
"react-router-dom": "7.18.2",
"zod": "4.2.0"
},
"devDependencies": {
"@medusajs/test-utils": "2.20.1",
"@swc/core": "^1.7.28",
"@swc/jest": "^0.2.36",
"@types/jest": "^29.5.13",
"@types/node": "^20.12.11",
"@types/react": "^18.3.2",
"@types/react-dom": "^18.2.25",
"jest": "^29.7.0",
"prop-types": "^15.8.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"ts-node": "^10.9.2",
"typescript": "^5.6.2",
"vite": "^7.3.6",
"yalc": "^1.0.0-pre.53"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"packageManager": "pnpm@10.28.2"
}
Node.js version
v24.20.0
Database and its version
PostgreSQL 16.15, official Alpine Docker image pinned by digest in the reproduction launcher.
Operating system name and version
Ubuntu 26.04.1 LTS, x86_64.
Browser name
Not applicable. Reproduced by invoking the native workflow through medusaIntegrationTestRunner.
What happended?
On Medusa 2.20.1, deleteProductVariantsWorkflow deletes a variant and its native price set, but leaves a linked custom record active despite deleteCascade: true.
The reproduction uses unmodified published packages and a small Brand module. Its link is defined using the standard descriptor:
export default defineLink(ProductModule.linkable.productVariant, {
linkable: BrandModule.linkable.brand,
deleteCascade: true,
})
Steps to reproduce:
- Create a product variant and a Brand record.
- Link them using
product_variant_id and brand_id.
- Run
deleteProductVariantsWorkflow(container).run({ input: { ids: [variant.id] } }).
- List the Brand record through its module service. It is still active.
The repository automates these steps with medusaIntegrationTestRunner and real PostgreSQL. With Node 24+, pnpm 10.28.2 and Docker:
git clone https://github.com/brunoocal/medusa-variant-link-repro.git
cd medusa-variant-link-repro
git checkout 5665d0263a4e28867f324a4f422027d70bdaf767
pnpm install --frozen-lockfile
pnpm reproduce
The command creates and removes its own disposable PostgreSQL container. No .env, existing database or Admin account is needed. Expected reproduction result: one passing test, one failing test, exit code 1.
Expected behavior
The workflow should soft-delete the linked custom record when deleting the variant, because the link enables deleteCascade: true.
Step 3 of the official digital products recipe uses this same variant descriptor and cascade option, and describes deleting the linked custom record when the variant is deleted.
Actual behavior
- The variant is deleted.
- Its native price set is deleted.
- The linked Brand record remains active with
deleted_at: null.
A separate control test calls link.delete({ product: { product_variant_id: variant.id } }). That correctly deletes the custom record, and link.restore restores it.
Both tests use real Medusa services and PostgreSQL. There are no internal mocks, retries or forceExit. The failure was also reproduced from a clean checkout. Build, strict typecheck and Medusa lint pass.
The workflow currently passes only variant_id to removeRemoteLinkStep, while the standard descriptor generates product_variant_id. This appears to explain the difference between the workflow and the direct Link.delete call. I can follow up with a regression test and a fix PR once the expected handling of these keys is confirmed.
This reproduction covers individual variant deletion through the workflow, not the HTTP endpoint, parent-product deletion or Redis providers. The captured output includes Node's experimental VM Modules warning and connection warnings from the test runner. Jest exits naturally with the failing assertion.
Link to reproduction repo
https://github.com/brunoocal/medusa-variant-link-repro
Reproduction commit: 5665d0263a4e28867f324a4f422027d70bdaf767.
Created with GPT-6 Astra in Codex.
Package.json file
Backend package generated with
create-medusa-app@2.20.1 --version 2.20.1. All Medusa packages below are unmodified npm releases. The root workspace configuration and pnpm lockfile are included in the reproduction repository.{ "name": "@dtc/backend", "version": "0.0.1", "description": "A starter for Medusa projects.", "author": "Medusa (https://medusajs.com)", "license": "MIT", "keywords": [ "sqlite", "postgres", "typescript", "ecommerce", "headless", "medusa" ], "scripts": { "build": "medusa build", "start": "medusa start", "dev": "medusa develop", "lint": "medusa lint", "test:integration:http": "jest --runInBand" }, "dependencies": { "@medusajs/admin-sdk": "2.20.1", "@medusajs/admin-shared": "2.20.1", "@medusajs/caching": "2.20.1", "@medusajs/cli": "2.20.1", "@medusajs/dashboard": "2.20.1", "@medusajs/draft-order": "2.20.1", "@medusajs/framework": "2.20.1", "@medusajs/medusa": "2.20.1", "@medusajs/ui": "4.2.3", "@tanstack/react-query": "5.64.2", "react-i18next": "13.5.0", "react-router-dom": "7.18.2", "zod": "4.2.0" }, "devDependencies": { "@medusajs/test-utils": "2.20.1", "@swc/core": "^1.7.28", "@swc/jest": "^0.2.36", "@types/jest": "^29.5.13", "@types/node": "^20.12.11", "@types/react": "^18.3.2", "@types/react-dom": "^18.2.25", "jest": "^29.7.0", "prop-types": "^15.8.1", "react": "^18.3.1", "react-dom": "^18.3.1", "ts-node": "^10.9.2", "typescript": "^5.6.2", "vite": "^7.3.6", "yalc": "^1.0.0-pre.53" }, "engines": { "node": "^20.19.0 || >=22.12.0" }, "packageManager": "pnpm@10.28.2" }Node.js version
v24.20.0
Database and its version
PostgreSQL 16.15, official Alpine Docker image pinned by digest in the reproduction launcher.
Operating system name and version
Ubuntu 26.04.1 LTS, x86_64.
Browser name
Not applicable. Reproduced by invoking the native workflow through
medusaIntegrationTestRunner.What happended?
On Medusa 2.20.1,
deleteProductVariantsWorkflowdeletes a variant and its native price set, but leaves a linked custom record active despitedeleteCascade: true.The reproduction uses unmodified published packages and a small Brand module. Its link is defined using the standard descriptor:
Steps to reproduce:
product_variant_idandbrand_id.deleteProductVariantsWorkflow(container).run({ input: { ids: [variant.id] } }).The repository automates these steps with
medusaIntegrationTestRunnerand real PostgreSQL. With Node 24+, pnpm 10.28.2 and Docker:git clone https://github.com/brunoocal/medusa-variant-link-repro.git cd medusa-variant-link-repro git checkout 5665d0263a4e28867f324a4f422027d70bdaf767 pnpm install --frozen-lockfile pnpm reproduceThe command creates and removes its own disposable PostgreSQL container. No
.env, existing database or Admin account is needed. Expected reproduction result: one passing test, one failing test, exit code 1.Expected behavior
The workflow should soft-delete the linked custom record when deleting the variant, because the link enables
deleteCascade: true.Step 3 of the official digital products recipe uses this same variant descriptor and cascade option, and describes deleting the linked custom record when the variant is deleted.
Actual behavior
deleted_at: null.A separate control test calls
link.delete({ product: { product_variant_id: variant.id } }). That correctly deletes the custom record, andlink.restorerestores it.Both tests use real Medusa services and PostgreSQL. There are no internal mocks, retries or
forceExit. The failure was also reproduced from a clean checkout. Build, strict typecheck and Medusa lint pass.The workflow currently passes only
variant_idtoremoveRemoteLinkStep, while the standard descriptor generatesproduct_variant_id. This appears to explain the difference between the workflow and the directLink.deletecall. I can follow up with a regression test and a fix PR once the expected handling of these keys is confirmed.This reproduction covers individual variant deletion through the workflow, not the HTTP endpoint, parent-product deletion or Redis providers. The captured output includes Node's experimental VM Modules warning and connection warnings from the test runner. Jest exits naturally with the failing assertion.
Link to reproduction repo
https://github.com/brunoocal/medusa-variant-link-repro
Reproduction commit:
5665d0263a4e28867f324a4f422027d70bdaf767.Created with GPT-6 Astra in Codex.