Is it incorrect to call save! without modifying a resource?

Topic summary

A developer using shopify_api gem version 13.3.1 with REST Admin API 2023-04 encounters errors when calling save! on resources without modifications.

Key findings:

  • Calling save! on an existing CustomCollection (fetched via find) without changes throws: “Required parameter missing or invalid”
  • Creating a new Product object and calling save! immediately also fails with the same error
  • Setting the product’s title attribute before saving resolves the error

Core question:
Does the Shopify API permit saving a resource without modifying it first?

Current status:
The issue appears related to validation requirements—the API may require certain fields (like title for products) to be present or changed before accepting a save operation. The discussion seeks clarification on whether this is expected API behavior or a potential bug.

Summarized with AI on November 12. AI used: claude-sonnet-4-5-20250929.

gem shopify_api 13.3.1

REST Admin API 2023-04

We are getting errors when saving a custom collection:

[88] pry(main)> shopify_collection = ShopifyAPI::CustomCollection.find(id: 276483506289)

[89] pry(main)> shopify_collection.save!
ShopifyAPI::Errors::HttpResponseError: {"errors":{"custom_collection":"Required parameter missing or invalid"},"error_reference":"If you report this error, please include this id: 10c5dbb8-f353-4eef-9e1b-02d2afbb3820."}
from /Users/alain/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/shopify_api-13.3.1/lib/shopify_api/clients/http_client.rb:75:in `request'
[90] pry(main)>

So, my question is: does the API allow saving a resource without having modified it?

I tired another resource, the Product:

[156] pry(main)> product = ShopifyAPI::Product.new

[157] pry(main)> product.save!
ShopifyAPI::Errors::HttpResponseError: {"errors":{"product":"Required parameter missing or invalid"},"error_reference":"If you report this error, please include this id: 49192984-0e1c-45ee-a1b6-59f9925167b2."}
from /Users/alain/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/shopify_api-13.3.1/lib/shopify_api/clients/http_client.rb:75:in `request'
[158] pry(main)>

So, I thought maybe it’s because the title is nil, so I modified the title and the save succeeds:

[158] pry(main)> product.title
=> nil
[159] pry(main)> product.title = 'p1'
=> "p1"
[160] pry(main)> product.save!
=> T::Private::Types::Void::VOID
[161] pry(main)>

but if I save one more time:

[161] pry(main)> product.save!
ShopifyAPI::Errors::HttpResponseError: {"errors":{"product":"Required parameter missing or invalid"},"error_reference":"If you report this error, please include this id: 3aa8bec7-bac6-4294-81e5-2e3e0721a8d0."}
from /Users/alain/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/shopify_api-13.3.1/lib/shopify_api/clients/http_client.rb:75:in `request'
[162] pry(main)>

and several more times, it generates different error id’s:

[161] pry(main)> product.save!
ShopifyAPI::Errors::HttpResponseError: {"errors":{"product":"Required parameter missing or invalid"},"error_reference":"If you report this error, please include this id: 3aa8bec7-bac6-4294-81e5-2e3e0721a8d0."}
from /Users/alain/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/shopify_api-13.3.1/lib/shopify_api/clients/http_client.rb:75:in `request'
[162] pry(main)> product.save!
ShopifyAPI::Errors::HttpResponseError: {"errors":{"product":"Required parameter missing or invalid"},"error_reference":"If you report this error, please include this id: 2c6fbaad-5074-4e06-b72a-36edfb539a56."}
from /Users/alain/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/shopify_api-13.3.1/lib/shopify_api/clients/http_client.rb:75:in `request'
[163] pry(main)> product.save!
ShopifyAPI::Errors::HttpResponseError: {"errors":{"product":"Required parameter missing or invalid"},"error_reference":"If you report this error, please include this id: f7d7ad48-ff57-494e-92ee-14cc6e353fad."}
from /Users/alain/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/shopify_api-13.3.1/lib/shopify_api/clients/http_client.rb:75:in `request'
[164] pry(main)> product.save!
ShopifyAPI::Errors::HttpResponseError: {"errors":{"product":"Required parameter missing or invalid"},"error_reference":"If you report this error, please include this id: 6d76bbbe-9bd7-42a8-aa19-9c1ce3a763a2."}
from /Users/alain/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/shopify_api-13.3.1/lib/shopify_api/clients/http_client.rb:75:in `request'
[165] pry(main)> product.save!
ShopifyAPI::Errors::HttpResponseError: {"errors":{"product":"Required parameter missing or invalid"},"error_reference":"If you report this error, please include this id: 07cd884f-0c98-4005-9cad-2cc4f9fe184b."}
from /Users/alain/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/shopify_api-13.3.1/lib/shopify_api/clients/http_client.rb:75:in `request'
[166] pry(main)> product.errors
=> #<ShopifyAPI::Rest::BaseErrors:0x0000000120ca7120
 @errors=
  [#<ShopifyAPI::Errors::HttpResponseError: {"errors":{"product":"Required parameter missing or invalid"},"error_reference":"If you report this error, please include this id: 49192984-0e1c-45ee-a1b6-59f9925167b2."}>,
   #<ShopifyAPI::Errors::HttpResponseError: {"errors":{"product":"Required parameter missing or invalid"},"error_reference":"If you report this error, please include this id: 3aa8bec7-bac6-4294-81e5-2e3e0721a8d0."}>,
   #<ShopifyAPI::Errors::HttpResponseError: {"errors":{"product":"Required parameter missing or invalid"},"error_reference":"If you report this error, please include this id: 2c6fbaad-5074-4e06-b72a-36edfb539a56."}>,
   #<ShopifyAPI::Errors::HttpResponseError: {"errors":{"product":"Required parameter missing or invalid"},"error_reference":"If you report this error, please include this id: f7d7ad48-ff57-494e-92ee-14cc6e353fad."}>,
   #<ShopifyAPI::Errors::HttpResponseError: {"errors":{"product":"Required parameter missing or invalid"},"error_reference":"If you report this error, please include this id: 6d76bbbe-9bd7-42a8-aa19-9c1ce3a763a2."}>,
   #<ShopifyAPI::Errors::HttpResponseError: {"errors":{"product":"Required parameter missing or invalid"},"error_reference":"If you report this error, please include this id: 07cd884f-0c98-4005-9cad-2cc4f9fe184b."}>]>
[167] pry(main)>

but if I modify the title again:

[167] pry(main)> product.title = 'p2'
=> "p2"
[168] pry(main)> product.save!
=> T::Private::Types::Void::VOID
[169] pry(main)>

then it’s all fine.

So my 3 questions are:

  1. Why do I get an error if I update a resource with the same values?
  2. Why is the error saying that a required paramter is missing or invalid?
  3. Why does the error id change every time I call save! ?

Thanks