Cart Transform - Input returning invalid cartline id

Summary On a very small number of carts, our Cart Transform function’s input query returns a cart line whose id is an empty global ID gid://shopify/CartLine/ with nothing after the trailing slash. When we pass that id back as the cartLineId of a lineExpand operation, the function output is rejected (InvalidOutputError) with:

[{"path":["operations",0,"lineExpand","cartLineId"],"explanation":"Invalid global id 'gid://shopify/CartLine/'","message":"Invalid global id 'gid://shopify/CartLine/'"}]

This has affected only 4 carts out of millions of Cart Transform runs that succeed every day, which makes it look like an edge-case on the input side rather than our function logic, we pass line.id straight through and don’t build the GID ourselves.

Environment

  • Function: Cart Transform
  • Functions API version: 2026-01
  • Operation used: lineExpand (bundle expansion)

Input query

graphql

query Input {
  cart {
    lines {
      id
    }
  }
}

Expected Every cart.lines[].id is a valid CartLine GID (e.g.gid://shopify/CartLine/<uuid>). We reference that id as cartLineId in our lineExpand operation.

Actual For the affected carts, a line comes back with an empty id:

JSON

"cart": {
    "lines": [
      { 
        "id": "gid:\/\/shopify\/CartLine\/" 
      }
    ]
  }

Because the id is empty, the cartLineId we emit is gid://shopify/CartLine/, and the output fails validation:

[{"path":["operations",0,"lineExpand","cartLineId"],"explanation":"Invalid global id 'gid://shopify/CartLine/'","message":"Invalid global id 'gid://shopify/CartLine/'"}]

Scope / frequency

  • 2 distinct merchants affected, 3 occurrences on the same merchant store, one on a second
  • It doesn’t look like these products went through regular storefront cart UI, line item properties our app attaches when a bundle is configured are missing from the input

What we’ve checked

  • Our function reads line.id from the input and passes it through unchanged, we don’t construct the CartLine GID, so the empty token originates in the function input.

Questions for Shopify

  1. Under what conditions can cart.lines[].id be returned as an empty gid://shopify/CartLine/ in a Cart Transform input?
  2. Is this a known issue on a particular API version, and is there a fix or recommended workaround?
  3. As a defensive measure, is it safe for us to skip/no-op any line whose id doesn’t match gid://shopify/CartLine/<non-empty> so the run doesn’t fail? Could that cause the line to be mis-handled at checkout?

I’m happy to share any further store id/function run id details in a DM.

Thanks

Hey @Gabrielle_Rea, I had a quick look into this and it looks like you’ve diagnosed this correctly. Passing line.id straight through to cartLineId is the documented approach for lineExpand, so the empty token doesn’t appear to be coming from your function. An empty gid://shopify/CartLine/ suggests the line reached the function input without a resolvable cart line id, which is unexpected. I’d want the owning team to confirm exactly why before saying anything definitive however.

On your defensive measure question, skipping or no-op’ing any line whose id doesn’t match gid://shopify/CartLine/<non-empty> should be safe as a guard. A line with an empty id can’t be targeted by a lineExpand operation anyway, so skipping it shouldn’t drop or mishandle a valid, expandable line. The tradeoff is that the affected line would go through checkout without being expanded into its components, so if those rare carts rely on the expansion for pricing or inventory, they may still need a manual look. That’s the main reason I’d like to dig into the root cause.

Since these carts will involve store-specific data, I’ll open a DM with you to collect the details.

Once I have those I can dig into how the line ended up without an id and get the right internal team to confirm the cause and any fix. I’ll keep this thread updated as I hear back, cheers!

@Gabrielle_Rea Thanks for sending those over, that was enough to trace the runs on our side. Your function logic is fine here, passing line.id() straight to lineExpand.cartLineId is the documented pattern for the customized bundle example, so the empty gid://shopify/CartLine/ isn’t coming from your code.

I’ve raised it with the team that owns Cart Transform so they can look at why the line is reaching the function input without a resolvable id, and shared the run details with them.

I’ll update here as I hear back, thanks again!

@Gabrielle_Rea got an update back on this, and your understanding was spot on. The empty gid://shopify/CartLine/ isn’t coming from your function. Passing line.id straight through to lineExpand.cartLineId is the documented pattern for the customized bundle example, so your logic is fine.

On those rare carts the cart line reaches the function input without a resolvable id, so the token comes back empty and then fails output validation. It lines up with what you noticed about those lines not going through the normal storefront cart flow and missing your app’s line-item properties. A blank line id slipped in upstream rather than being generated by your code.

The safe guard is exactly what you proposed. Skip or no-op any line whose id doesn’t match gid://shopify/CartLine/<non-empty> before emitting a lineExpand operation. A line with an empty id can’t be targeted anyway, so skipping it won’t drop a valid expandable line. The only tradeoff is that the affected line goes through checkout unexpanded, so if any of those carts rely on the expansion for pricing or inventory they may need a manual look.

That guard is safe to ship now. On the input side, I’ve raised the empty-id case with the relevant team so they can tighten up validation and stop a blank id from reaching the function input in the first place - thanks for raising this!