nopSolutions/nopCommerce · error · NopException

Exchange ratio not set for dimension [{targetMeasureDimensio

Error message

Exchange ratio not set for dimension [{targetMeasureDimension.Name}]

What it means

Thrown by ConvertFromPrimaryMeasureDimensionAsync as a NopException when targetMeasureDimension.Ratio equals decimal.Zero. Dimension conversion multiplies by the dimension's Ratio relative to the base dimension; a zero ratio would zero the result, so the guard rejects it. Also note GetMeasureDimensionByIdAsync(BaseDimensionId) is dereferenced without a null check — a missing base dimension would NullReferenceException before this line.

Source

Thrown at src/Libraries/Nop.Services/Directory/MeasureService.cs:174

    /// <param name="value">Value to convert</param>
    /// <param name="targetMeasureDimension">Target dimension</param>
    /// <returns>
    /// A task that represents the asynchronous operation
    /// The task result contains the converted value
    /// </returns>
    public virtual async Task<decimal> ConvertFromPrimaryMeasureDimensionAsync(decimal value,
        MeasureDimension targetMeasureDimension)
    {
        ArgumentNullException.ThrowIfNull(targetMeasureDimension);

        var result = value;
        var baseDimensionIn = await GetMeasureDimensionByIdAsync(_measureSettings.BaseDimensionId);
        if (result == decimal.Zero || targetMeasureDimension.Id == baseDimensionIn.Id)
            return result;

        var exchangeRatio = targetMeasureDimension.Ratio;
        if (exchangeRatio == decimal.Zero)
            throw new NopException($"Exchange ratio not set for dimension [{targetMeasureDimension.Name}]");
        result *= exchangeRatio;

        return result;
    }

    /// <summary>
    /// Converts to primary measure dimension
    /// </summary>
    /// <param name="value">Value to convert</param>
    /// <param name="sourceMeasureDimension">Source dimension</param>
    /// <returns>
    /// A task that represents the asynchronous operation
    /// The task result contains the converted value
    /// </returns>
    public virtual async Task<decimal> ConvertToPrimaryMeasureDimensionAsync(decimal value,
        MeasureDimension sourceMeasureDimension)
    {
        ArgumentNullException.ThrowIfNull(sourceMeasureDimension);

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Set a non-zero Ratio for the target measure dimension in Admin > Configuration > Measures.
  2. Ensure MeasureSettings.BaseDimensionId points to a valid dimension (avoid the latent NRE on baseDimensionIn.Id).
  3. Validate dimension.Ratio > 0 before calling the conversion.

Example fix

// before
var value = await _measureService.ConvertFromPrimaryMeasureDimensionAsync(qty, dimension);

// after
if (dimension.Ratio == decimal.Zero)
    throw new InvalidOperationException($"Dimension '{dimension.Name}' has no ratio set.");
var value = await _measureService.ConvertFromPrimaryMeasureDimensionAsync(qty, dimension);
Defensive patterns

Strategy: validation

Validate before calling

if (targetMeasureDimension.Ratio == decimal.Zero)
    throw new InvalidOperationException($"Dimension '{targetMeasureDimension.Name}' has no ratio.");

Type guard

static bool HasRatio(MeasureDimension d) => d is not null && d.Ratio != decimal.Zero;

Try / catch

try { await _measureService.ConvertFromPrimaryMeasureDimensionAsync(value, dim); }
catch (NopException ex) when (ex.Message.Contains("Exchange ratio not set"))
{ _logger.LogWarning(ex, "Missing dimension ratio; skipping conversion."); }

Prevention

When it happens

Trigger: Calling ConvertFromPrimaryMeasureDimensionAsync(value, dimension) where dimension.Rate/Ratio is 0 and the dimension differs from the configured base dimension. Triggers on any non-zero value being converted to a ratio-less dimension.

Common situations: A measure dimension (e.g., a custom unit) was added but its Ratio to the base dimension was never set; admin reset ratios; import wrote Ratio=0; base dimension misconfigured.

Related errors


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