Shopify Function RuntimeError when cart contains CustomProduct (missing id field)

Hi everyone,

We’re facing a runtime error in our Shopify Product Discount Function when a custom product is added to the cart by the client.

App / Function Details

  • Extension Type: Product Discounts

  • Target: purchase.product-discount.run

  • API Version: product_discounts 2025-0

  • Error Type: RuntimeError


Issue Description

When a customer adds a custom product (created via line item properties or custom product flow) to the cart, our function crashes with the following error:

called `Result::unwrap()` on an `Err` value: Error("missing field `id`", line: 1, column: 370)

Input (STDIN)

The cart line looks like this:

{
  "quantity": 1,
  "cost": {
    "amountPerQuantity": {
      "amount": "10.0",
      "currencyCode": "USD"
    }
  },
  "merchandise": {
    "__typename": "CustomProduct"
  }
}

As you can see, merchandise has:

"__typename": "CustomProduct"

but it does not contain an id field.


Error Logs (STDERR)

thread '<unnamed>' panicked at src/run.rs:144:1:
called `Result::unwrap()` on an `Err` value: Error("missing field `id`", line: 1, column: 370)

WASM backtrace:

error while executing at wasm backtrace:
0: <unknown>!<wasm function 360>
1: <unknown>!<wasm function 72>
2: <unknown>!<wasm function 110>
3: <unknown>!<wasm function 140> (trap code: Unreachable)


Root Cause (Suspected)

Our Rust code expects:

line.merchandise.id.unwrap()

But for CustomProduct, there is no id field in the input payload, which causes deserialization to fail and the function to panic.


Questions

  1. Is this expected behavior that CustomProduct does not contain an id in Shopify Functions input?

  2. What is the recommended way to safely handle CustomProduct lines in a Product Discount function?

  3. Should we:

    • Explicitly match on __typename and skip CustomProduct?

    • Use an enum for ProductVariant | CustomProduct and handle it conditionally?

    • Or is there a better pattern recommended by Shopify?


What We Want

We want to:

  • Avoid runtime panics

  • Gracefully skip unsupported line types

  • Ensure the function still runs for normal ProductVariant lines

Any guidance or best practices would be greatly appreciated.

Thanks in advance!

Don’t use .unwrap() in production Rust code - ever. It doesn’t make sense for a custom product to have an id, so you need to handle that scenario gracefully.