Why is the first variant automatically added to my cart?

Topic summary

A user is experiencing an issue where product variant selections are not being respected when adding items to cart. Instead of adding the chosen variant, the system defaults to the first available option every time.

Problem Details:

  • Affects all products with variants on their Shopify store
  • An error screenshot was provided showing the issue
  • Example product link included for reference

Code Context:

  • The user shared their product item template code
  • The code appears to be a Shopify Liquid template handling product display, images, pricing, and color swatches
  • Code snippet shows logic for product images, alternate images, pricing display, and color variant rendering

Current Status:

  • No solution has been provided yet
  • The discussion remains open with the user seeking help to resolve the variant selection bug
Summarized with AI on November 19. AI used: claude-sonnet-4-5-20250929.

Hi all, hoping I can get an answer to this as its driving me crazy.

Every time I try to add a variant product to the cart it only ever puts the first option in. You can use this item as an example: https://theessenceinc.com/products/rose-gold-brightening-facial-treatment-mask?variant=45327634202914 but it’s the same issue for all products with a variant.

I’m getting this error:

This is my code:

<div class="ProductItem {% if use_horizontal %}ProductItem--horizontal{% endif %}">
  <div class="ProductItem__Wrapper">
    {%- comment -%}
      We are using LazySizes to efficiently choose the most appropriate image in the set. However, because internally LazySizes uses srcset, we need to make
      sure that the image sizes we offer is not larger than the max size uploaded by the merchants.
    {%- endcomment -%}

    {%- if settings.product_image_size == 'natural' or use_horizontal -%}
      {%- assign use_natural_size = true -%}
    {%- else -%}
      {%- assign use_natural_size = false -%}
    {%- endif -%}

    {%- if settings.product_show_secondary_image and product.media[1] != blank and use_horizontal != true -%}
      {%- assign has_alternate_image = true -%}
    {%- else -%}
      {%- assign has_alternate_image = false -%}
    {%- endif -%}

    <a
      href="{{ product.url }}"
      class="ProductItem__ImageWrapper {% if has_alternate_image %}ProductItem__ImageWrapper--withAlternateImage{% endif %}"
    >
      {%- if use_horizontal -%}
        {%- assign max_width = 125 -%}
      {%- else -%}
        {%- assign max_width = product.featured_media.preview_image.width -%}
      {%- endif -%}

      {%- assign media_aspect_ratio = product.featured_media.aspect_ratio
        | default: product.featured_media.preview_image.aspect_ratio
      -%}

      <div
        class="AspectRatio AspectRatio--{% if use_natural_size %}withFallback{% else %}{{ settings.product_image_size }}{% endif %}"
        style="max-width: {{ max_width }}px; {% if use_natural_size %}padding-bottom: {{ 100.0 | divided_by: media_aspect_ratio }}%;{% endif %} --aspect-ratio: {{ media_aspect_ratio }}"
      >
        {%- comment -%}
          IMPLEMENTATION NOTE: The alternate image (not visible by default) should be the first in the DOM, as the spinner (Image__Loader element) is
          displayed based on the immediately previously shown image.
        {%- endcomment -%}

        {%- if has_alternate_image -%}
          {%- capture supported_sizes -%}{%- render 'image-size', sizes: '200,300,400,600,800,900,1000,1200', image: product.media[1] -%}{%- endcapture -%}

          {%- assign image_url = product.media[1] | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}

          <img
            class="ProductItem__Image ProductItem__Image--alternate Image--lazyLoad Image--fadeIn"
            data-src="{{ image_url }}"
            data-widths="[{{ supported_sizes }}]"
            data-sizes="auto"
            alt="{{ product.media[1].alt | escape }}"
            data-media-id="{{ product.media[1].id }}"
          >
        {%- endif -%}

        {%- capture supported_sizes -%}{%- render 'image-size', sizes: '200,400,600,700,800,900,1000,1200', image: product.featured_media -%}{%- endcapture -%}
        {%- assign image_url = product.featured_media | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}

        <img
          class="ProductItem__Image Image--lazyLoad Image--fadeIn"
          data-src="{{ image_url }}"
          data-widths="[{{ supported_sizes }}]"
          data-sizes="auto"
          alt="{{ product.featured_media.alt | escape }}"
          data-media-id="{{ product.featured_media.id }}"
        >
        <span class="Image__Loader"></span>

        <noscript>
          <img
            class="ProductItem__Image ProductItem__Image--alternate"
            src="{{ product.media[1] | img_url: '600x' }}"
            alt="{{ product.media[1].alt | escape }}"
          >
          <img
            class="ProductItem__Image"
            src="{{ product.featured_media| img_url: '600x' }}"
            alt="{{ product.featured_media.alt | escape }}"
          >
        </noscript>
      </div>
    </a>

    {%- if show_labels -%}
      {%- capture product_labels -%}
        {%- for tag in product.tags -%}
          {%- if tag contains '__label' -%}
            <span class="ProductItem__Label Heading Text--subdued">{{ tag | split: '__label:' | last }}</span>
            {%- break -%}
          {%- endif -%}
        {%- endfor -%}

        {%- if product.available -%}
          {%- if product.compare_at_price > product.price -%}
            <span class="ProductItem__Label ProductItem__Label--onSale Heading Text--subdued">{{ 'product.labels.on_sale' | t }}</span>
          {%- endif -%}
        {%- else -%}
          <span class="ProductItem__Label ProductItem__Label--soldOut Heading Text--subdued">{{ 'product.labels.sold_out' | t }}</span>
        {%- endif -%}
      {%- endcapture -%}

      {%- if product_labels != blank -%}
        <div class="ProductItem__LabelList">
          {{ product_labels }}
        </div>
      {%- endif -%}
    {%- endif -%}

    {%- if show_product_info -%}
      <div class="ProductItem__Info {% unless use_horizontal %}ProductItem__Info--{{ settings.product_info_alignment }}{% endunless %}">
        {%- if show_vendor -%}
          <p class="ProductItem__Vendor Heading">{{ product.vendor }}</p>
        {%- endif -%}

        <h2 class="ProductItem__Title Heading">
          <a href="{{ product.url }}">{{ product.title }}</a>
        </h2>

        {%- if settings.show_product_rating -%}
          {%- unless use_horizontal -%}
            <div class="ProductItem__Rating Heading Text--subdued u-h7">
              {%- render 'product-rating', product: product -%}
            </div>
          {%- endunless -%}
        {%- endif -%}

        {%- if show_color_swatch -%}
          {%- assign color_swatch_list = '' -%}

          {%- capture color_swatch -%}
            {%- assign color_label = 'color,colour,couleur,colore,farbe,색,色,färg,farve' | split: ',' -%}
            {%- assign color_swatch_config = settings.color_swatch_config | newline_to_br | split: '<br />' -%}
            {%- capture color_name -%}{{ section.id }}-{{ product.id }}{%- endcapture -%}

            {%- for option in product.options_with_values -%}
              {%- assign downcased_option = option.name | downcase -%}

              {%- if color_label contains downcased_option -%}
                {%- assign variant_option = 'option' | append: forloop.index -%}

                {%- for value in option.values -%}
                  {%- assign downcased_value = value | downcase -%}
                  {%- capture color_id -%}{{ section.id }}-{{ product.id }}-{{ forloop.index }}{%- endcapture -%}

                  {%- for variant in product.variants -%}
                    {%- if variant[variant_option] == value -%}
                      {%- assign variant_for_value = variant -%}
                      {%- break -%}
                    {%- endif -%}
                  {%- endfor -%}

                  <div class="ProductItem__ColorSwatchItem">
                    {%- if variant_for_value.image -%}
                      {%- capture supported_sizes -%}{%- render 'image-size', sizes: '200,400,600,700,800,900,1000,1200', image: variant_for_value.image -%}{%- endcapture -%}
                      {%- assign variant_image_url = variant_for_value.image | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}
                    {%- endif -%}

                    <input class="ColorSwatch__Radio" type="radio" name="{{ color_name }}" id="{{ color_id }}" value="{{ value | escape }}" {% if option.selected_value == value %}checked="checked"{% endif %} data-variant-url="{{ variant_for_value.url }}{% if variant_for_value.image %}#Image{{ variant_for_value.image.id }}{% endif %}" {% if variant_for_value.image %}data-image-id="{{ variant_for_value.image.id }}" data-image-url="{{ variant_image_url }}" data-image-widths="[{{ supported_sizes }}]" data-image-aspect-ratio="{{ variant_for_value.image.aspect_ratio }}"{% endif %} aria-hidden="true">
                    <label class="ColorSwatch ColorSwatch--small {% if downcased_value == 'white' %}ColorSwatch--white{% endif %}" for="{{ color_id }}" style="{% render 'color-swatch-style', color_swatch_config: color_swatch_config, value: value %}" title="{{ value | escape }}" data-tooltip="{{ value | escape }}"></label>
                  </div>
                {%- endfor -%}
              {%- endif -%}
            {%- endfor -%}
          {%- endcapture -%}

          {%- if color_swatch != blank -%}
            {%- capture color_swatch_list -%}
              <div class="ProductItem__ColorSwatchList">
                {{- color_swatch -}}
              </div>
            {%- endcapture -%}
          {%- endif -%}
        {%- endif -%}

        {%- if show_price_on_hover == null -%}
          {%- assign show_price_on_hover = settings.product_show_price_on_hover -%}
        {%- endif -%}

        {%- if show_price_on_hover and color_swatch_list != blank -%}
          {{- color_swatch_list -}}
        {%- endif -%}

        {%- if product.template_suffix != 'coming-soon' -%}
          {%- if product.template_suffix == 'br-product' -%}
            {% if customer %}
              <div class="ProductItem__PriceList {% if show_price_on_hover %}ProductItem__PriceList--showOnHover{% endif %} Heading">
                {%- if product.compare_at_price > product.price -%}
                  {%- if settings.currency_code_enabled -%}
                    <span class="ProductItem__Price Price Price--highlight Text--subdued">
                      {{- product.price | money_with_currency -}}
                    </span>
                    <span class="ProductItem__Price Price Price--compareAt Text--subdued">
                      {{- product.compare_at_price | money_with_currency -}}
                    </span>
                  {%- else -%}
                    <span class="ProductItem__Price Price Price--highlight Text--subdued">
                      {{- product.price | money -}}
                    </span>
                    <span class="ProductItem__Price Price Price--compareAt Text--subdued">
                      {{- product.compare_at_price | money -}}
                    </span>
                  {%- endif -%}
                {%- elsif product.price_varies -%}
                  {%- if settings.currency_code_enabled -%}
                    {%- capture formatted_min_price -%}{{ product.price_min | money_with_currency }}{%- endcapture -%}
                    {%- capture formatted_max_price -%}{{ product.price_max | money_with_currency }}{%- endcapture -%}
                  {%- else -%}
                    {%- capture formatted_min_price -%}{{ product.price_min | money }}{%- endcapture -%}
                    {%- capture formatted_max_price -%}{{ product.price_max | money }}{%- endcapture -%}
                  {%- endif -%}

                  <span class="ProductItem__Price Price Text--subdued">
                    {{-
                      'collection.product.from_price_html'
                      | t: min_price: formatted_min_price, max_price: formatted_max_price
                    -}}
                  </span>
                {%- else -%}
                  {%- if settings.currency_code_enabled -%}
                    <span class="ProductItem__Price Price Text--subdued">
                      {{- product.price | money_with_currency -}}
                    </span>
                  {%- else -%}
                    <span class="ProductItem__Price Price Text--subdued">{{ product.price | money }}</span>
                  {%- endif -%}
                {%- endif -%}
              </div>
            {% else %}
              <div class="member-only">
                <p>LOG IN TO SEE PRICES</p>
              </div>
            {%- endif -%}
          {% else %}
            <div class="ProductItem__PriceList {% if show_price_on_hover %}ProductItem__PriceList--showOnHover{% endif %} Heading">
              {%- if product.compare_at_price > product.price -%}
                {%- if settings.currency_code_enabled -%}
                  <span class="ProductItem__Price Price Price--highlight Text--subdued">
                    {{- product.price | money_with_currency -}}
                  </span>
                  <span class="ProductItem__Price Price Price--compareAt Text--subdued">
                    {{- product.compare_at_price | money_with_currency -}}
                  </span>
                {%- else -%}
                  <span class="ProductItem__Price Price Price--highlight Text--subdued">
                    {{- product.price | money -}}
                  </span>
                  <span class="ProductItem__Price Price Price--compareAt Text--subdued">
                    {{- product.compare_at_price | money -}}
                  </span>
                {%- endif -%}
              {%- elsif product.price_varies -%}
                {%- if settings.currency_code_enabled -%}
                  {%- capture formatted_min_price -%}{{ product.price_min | money_with_currency }}{%- endcapture -%}
                  {%- capture formatted_max_price -%}{{ product.price_max | money_with_currency }}{%- endcapture -%}
                {%- else -%}
                  {%- capture formatted_min_price -%}{{ product.price_min | money }}{%- endcapture -%}
                  {%- capture formatted_max_price -%}{{ product.price_max | money }}{%- endcapture -%}
                {%- endif -%}

                <span class="ProductItem__Price Price Text--subdued">
                  {{-
                    'collection.product.from_price_html'
                    | t: min_price: formatted_min_price, max_price: formatted_max_price
                  -}}
                </span>
              {%- else -%}
                {%- if settings.currency_code_enabled -%}
                  <span class="ProductItem__Price Price Text--subdued">{{ product.price | money_with_currency }}</span>
                {%- else -%}
                  <span class="ProductItem__Price Price Text--subdued">{{ product.price | money }}</span>
                {%- endif -%}
              {%- endif -%}
            </div>
          {%- endif -%}

          {%- if product.selected_or_first_available_variant.unit_price_measurement -%}
            <div class="ProductItem__UnitPriceMeasurement">
              <div class="UnitPriceMeasurement Heading Text--subdued">
                <span class="UnitPriceMeasurement__Price">
                  {{- product.selected_or_first_available_variant.unit_price | money -}}
                </span>
                <span class="UnitPriceMeasurement__Separator">/ </span>

                <span
                  class="UnitPriceMeasurement__ReferenceValue"
                  {%- if product.selected_or_first_available_variant.unit_price_measurement.reference_value == 1 -%}
                    style="display: none"
                  {% endif %}
                >
                  {{- product.selected_or_first_available_variant.unit_price_measurement.reference_value -}}
                </span>

                <span class="UnitPriceMeasurement__ReferenceUnit">
                  {{- product.selected_or_first_available_variant.unit_price_measurement.reference_unit -}}
                </span>
              </div>
            </div>
          {%- endif -%}
        {%- endif -%}

        {%- if show_price_on_hover == false and color_swatch_list != blank -%}
          {{- color_swatch_list -}}
        {%- endif -%}
      </div>
    {%- endif -%}
  </div>

  {%- if use_horizontal -%}
    <a href="{{ product.url }}" class="ProductItem__ViewButton Button Button--secondary hidden-pocket">
      {{- 'collection.product.view_product' | t -}}
    </a>
  {%- endif -%}
</div>