nopSolutions/nopCommerce · error · NopException

Selected shipping option is unavailable

Error message

Selected shipping option is unavailable

What it means

Thrown when a specific shipping option was selected by the customer (selectedOptionId is non-empty) but no available shipping option matches that name. This indicates the previously chosen option is no longer in the list of available options returned by the shipping providers.

Source

Thrown at src/Plugins/Nop.Plugin.Payments.PayPalCommerce/Services/PayPalCommerceServiceManager.cs:675

        if (details.Placement == ButtonPlacement.PaymentMethod && !isApplePay)
        {
            shipping.Type = details.IsPickup
                ? ShippingType.SHIPPING.ToString().ToUpper() //PICKUP_IN_STORE option doesn't work for some reason
                : ShippingType.SHIPPING.ToString().ToUpper();

            return shipping;
        }

        var (shippingOptions, pickupPoints) = await PrepareShippingOptionsAsync(details);
        if (!shippingOptions?.Any() ?? true)
            throw new NopException("No available shipping options");

        var selectedShippingOption = shippingOptions.FirstOrDefault();
        if (!string.IsNullOrEmpty(selectedOptionId))
        {
            var existingOption = shippingOptions
                .FirstOrDefault(option => string.Equals(option.Name, selectedOptionId, StringComparison.InvariantCultureIgnoreCase))
                ?? throw new NopException("Selected shipping option is unavailable");

            selectedShippingOption = existingOption;
        }

        if (selectedShippingOption is null)
            throw new NopException("Selected shipping option is unavailable");

        PickupPoint pickupPoint = null;
        if (selectedShippingOption.IsPickupInStore)
        {
            pickupPoint = await pickupPoints.FirstOrDefaultAwaitAsync(async point =>
                string.Equals(await GetShippingOptionNameAsync(new() { Name = point.Name, IsPickupInStore = true }), selectedShippingOption.Name) &&
                string.Equals(point.ProviderSystemName, selectedShippingOption.ShippingRateComputationMethodSystemName));

            details.IsPickup = true;
            details.PickupPoint = pickupPoint;

            //if the shipping option type is set to PICKUP, then the full name should start with S2S meaning ship to store (for example, S2S My Store)

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Clear the stored shipping selection and prompt the customer to re-select a shipping option
  2. Verify shipping rate computation methods are consistently returning the same option names across requests
  3. Check for time-sensitive or rate-limited shipping options that may expire during checkout
  4. Ensure no concurrent configuration changes to shipping methods during active checkout sessions

Example fix

// before
var existingOption = shippingOptions
    .FirstOrDefault(option => string.Equals(option.Name, selectedOptionId, StringComparison.InvariantCultureIgnoreCase))
    ?? throw new NopException("Selected shipping option is unavailable");

// after
var existingOption = shippingOptions
    .FirstOrDefault(option => string.Equals(option.Name, selectedOptionId, StringComparison.InvariantCultureIgnoreCase));
if (existingOption is null)
{
    //fall back to the first available option instead of failing
    existingOption = shippingOptions.FirstOrDefault();
    await _logger.WarningAsync($"Selected shipping option '{selectedOptionId}' no longer available, falling back");
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate selected shipping option is still available
if (!string.IsNullOrEmpty(selectedOptionId))
{
    var options = await _shippingService.GetShippingOptionsAsync(cart, address, "", storeId);
    var exists = options.ShippingOptions.Any(o =>
        string.Equals(o.Name, selectedOptionId, StringComparison.InvariantCultureIgnoreCase));
    if (!exists)
        selectedOptionId = null; // reset to force re-selection
}

Try / catch

var (result, error) = await manager.PrepareShippingAsync(settings, details, selectedOptionId, isApplePay);
if (!string.IsNullOrEmpty(error) && error == "Selected shipping option is unavailable")
{
    //reset selection and retry with first available option
    var (retryResult, retryError) = await manager.PrepareShippingAsync(settings, details, null, isApplePay);
}

Prevention

When it happens

Trigger: PrepareShippingAsync receives a non-empty selectedOptionId; shippingOptions from PrepareShippingOptionsAsync contains options, but none have a Name matching selectedOptionId (case-insensitive comparison).

Common situations: The selected shipping method was deactivated or its rate expired between selection and payment; shipping provider rates changed between page loads; session-stored selection references a stale option name; shipping rate computation method returned different options due to configuration changes.

Related errors


AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13). Data as JSON: /api/errors/68b55877832aa865. Report an issue: GitHub.