Cart Transform API not working on version 2025-01

I was testing my Shopify App recently and noticed that the Cart Transform merge is no longer working on version 2025-01.

In the 2025-01 version of the API says that you use are supposed to use the term merge in the Shopify Function but the most up to date and stable version of the api (2025-07) it says you are supposed to use linesMerge.

Below I put a code block of the following:

  • My GraphQL input data
  • The contents of my run.js file
  • The output as Shown in my dev dashboard

If you take a look at my run.js code, you will see i am using the merge command at the end of the run function.

My code was working just a couple of weeks ago so I’m not sure what is going on. Please let me know how I can fix this.

//========== GraphQL Input Data for the Shopify Function

{
  "cart": {
    "lines": [
      {
        "id": "gid:\/\/shopify\/CartLine\/98a6b1a8-f7ec-401b-8287-b124c47c43fb",
        "quantity": 1,
        "bundleId": {
          "value": "5"
        }
      },
      {
        "id": "gid:\/\/shopify\/CartLine\/c6456931-21c8-4f66-8704-eed9314783fa",
        "quantity": 1,
        "bundleId": {
          "value": "5"
        }
      },
      {
        "id": "gid:\/\/shopify\/CartLine\/94714ab5-e458-4fe3-8d04-1c8ee44af690",
        "quantity": 1,
        "bundleId": {
          "value": "5"
        }
      },
      {
        "id": "gid:\/\/shopify\/CartLine\/b04dc235-3904-4643-8640-1a58ae37d680",
        "quantity": 1,
        "bundleId": {
          "value": "5"
        }
      }
    ]
  },
  "shop": {
    "metafield": {
      "value": "{\"parentVariantId\":\"gid:\/\/shopify\/ProductVariant\/51198624563487\",\"bundlesArray\":[{\"name\":\"Test Bundle\",\"id\":5,\"bundle_display_name\":\"\",\"bundle_checkout_title\":\"\",\"status\":\"active\",\"discount_type\":\"percentage\",\"static_discount_value\":\"20\",\"tiered_discounts\":\"[]\"}]}"
    }
  }
}


//========== Run.js file
export function run(input) {
  // Stores cart lines grouped by their bundle ID property
  const groupedItems = {};
  const metafieldData = JSON.parse(input.shop.metafield.value)

  const parentVariantId = metafieldData.parentVariantId
  const bundlesArray = metafieldData.bundlesArray
  const cartLines = input.cart.lines

  //console.log("VALUE OF Metafield Data post-parse", "Parent Gid: " + parentVariantId, "\n", "Bundles Array", bundlesArray)

  cartLines.forEach(line => {
    const bundleId = line.bundleId
    if(!bundleId?.value) return

    //create a new grouping for the bundle id if it doesn't have one yet
    if(!groupedItems[bundleId.value]){
      groupedItems[bundleId.value] = []
    }

    groupedItems[bundleId.value].push(line)
  })

  console.log(JSON.stringify(groupedItems))

  //Seems like this chunk of code is an array of arrays
  const cartOperations = Object.values(groupedItems).map(group => {
    const totalItemsInBundle = group.reduce((sum, line) => sum + line.quantity, 0);
    const bundleId = group[0].bundleId.value;

    const discountPercentage = calculatePercentageDiscount(bundlesArray, bundleId, totalItemsInBundle);
    const updatedBundleTitle = overrideBundleTitle(bundlesArray, bundleId);

    const lineItems = group.map(line => {
      return {
        cartLineId: line.id,
        quantity: line.quantity
      }
    })

    // console.log("Value of Line Items", JSON.stringify(lineItems))
    // console.log("Discount: " + discountPercentage)
    // console.log("Updated Title: " + updatedBundleTitle)

    return{
      merge: {
        cartLines: lineItems,
        //^ Variant ID of the Parent Product for the Bundler Cart Transform
        parentVariantId: parentVariantId,
        price: {
          percentageDecrease: {
            value: discountPercentage
          }
        },
        //Conditional object spread
        ...(updatedBundleTitle && { title: updatedBundleTitle })
      }
    }
  })

  return {
    operations: cartOperations
  }
};


function calculatePercentageDiscount(bundlesArray, bundleId, totalItemsInBundle) {
  const bundleConfig = bundlesArray.find(bundle => bundle.id == bundleId)

  if (!bundleConfig) {
    return 0;
  }
  if (bundleConfig.discount_type === "percentage") {
    return parseFloat(bundleConfig.static_discount_value) || 0;
  }
  if (bundleConfig.discount_type === "tiered_percentage") {
    const tieredDiscounts = JSON.parse(bundleConfig.tiered_discounts);
    const sortedTiers = tieredDiscounts.sort((a, b) => b.minItems - a.minItems);
    const applicableTier = sortedTiers.find(tier => totalItemsInBundle >= parseInt(tier.minItems));
    if (applicableTier) {
      return parseFloat(applicableTier.discount) || 0;
    }
  }
  return 0;
}

function overrideBundleTitle(bundlesArray, bundleId) {
  const bundleConfig = bundlesArray.find(bundle => bundle.id == bundleId);
  return bundleConfig?.bundle_checkout_title || null;
}

//========= Result of the Shopify Function:
{
  "operations": [
    {
      "linesMerge": {
        "cartLines": [
          {
            "cartLineId": "gid:\/\/shopify\/CartLine\/98a6b1a8-f7ec-401b-8287-b124c47c43fb",
            "quantity": 1
          },
          {
            "cartLineId": "gid:\/\/shopify\/CartLine\/c6456931-21c8-4f66-8704-eed9314783fa",
            "quantity": 1
          },
          {
            "cartLineId": "gid:\/\/shopify\/CartLine\/94714ab5-e458-4fe3-8d04-1c8ee44af690",
            "quantity": 1
          },
          {
            "cartLineId": "gid:\/\/shopify\/CartLine\/b04dc235-3904-4643-8640-1a58ae37d680",
            "quantity": 1
          }
        ],
        "parentVariantId": "gid:\/\/shopify\/ProductVariant\/51198624563487",
        "price": {
          "percentageDecrease": {
            "value": 20
          }
        }
      }
    }
  ]
}

And this what the result looks like in checkout:

Hey @Patrick_Pierre

If you use linesMerge on 2025-01 does this work? It’s possible there was a change to this version which may not have been documented.

@Liam-Shopify Thanks for your response.

I tried using linesMerge and I got the following error message:

[{"path":["operations",0],"explanation":"Expected one of valid values: expand, merge, update, lineAdd. Got: linesMerge"}]

I also tried updating the API version to 2025-07 in shopify.extension.toml file and using linesMerge still failed. And when I use merge, the logs don’t show any errors but the bundling is still unsuccessful.

Based on the code I posted, do you think I am making any other mistakes that might be causing this?

Hi again @Patrick_Pierre

From what I’m seeing you should use merge for 2025-01 and earlier and linesMerge for 2025-07 and later. Since this is not working as expected there could be other things to look out for like making sure your function export matches the target (e.g., cartTransformRun for 2025-07).

Also always regenerate types and check your input/output against the latest schema, and if you’re using the Shopify CLI, make sure to run shopify app function typegen after changing the API version.

If you’re still seeing no effect in the checkout after using the correct key, double-check that your function is being deployed and invoked, and that your input data matches the expected structure.