{"record":{"id":"bda92e2e827f1347","repo":"nopSolutions/nopCommerce","slug":"exchange-ratio-not-set-for-weight-sourcemeasurew","errorCode":null,"errorMessage":"Exchange ratio not set for weight [{sourceMeasureWeight.Name}]","messagePattern":"Exchange ratio not set for weight \\[(.+?)\\]","errorType":"exception","errorClass":"NopException","httpStatus":null,"severity":"error","filePath":"src/Libraries/Nop.Services/Directory/MeasureService.cs","lineNumber":375,"sourceCode":"    /// </summary>\r\n    /// <param name=\"value\">Value to convert</param>\r\n    /// <param name=\"sourceMeasureWeight\">Source weight</param>\r\n    /// <returns>\r\n    /// A task that represents the asynchronous operation\r\n    /// The task result contains the converted value\r\n    /// </returns>\r\n    public virtual async Task<decimal> ConvertToPrimaryMeasureWeightAsync(decimal value, MeasureWeight sourceMeasureWeight)\r\n    {\r\n        ArgumentNullException.ThrowIfNull(sourceMeasureWeight);\r\n\r\n        var result = value;\r\n        var baseWeightIn = await GetMeasureWeightByIdAsync(_measureSettings.BaseWeightId);\r\n        if (result == decimal.Zero || sourceMeasureWeight.Id == baseWeightIn.Id)\r\n            return result;\r\n\r\n        var exchangeRatio = sourceMeasureWeight.Ratio;\r\n        if (exchangeRatio == decimal.Zero)\r\n            throw new NopException($\"Exchange ratio not set for weight [{sourceMeasureWeight.Name}]\");\r\n        result /= exchangeRatio;\r\n\r\n        return result;\r\n    }\r\n\r\n    #endregion\r\n\r\n    #endregion\r\n}","sourceCodeStart":357,"sourceCodeEnd":384,"githubUrl":"https://github.com/nopSolutions/nopCommerce/blob/64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2/src/Libraries/Nop.Services/Directory/MeasureService.cs#L357-L384","documentation":"Thrown by MeasureService.ConvertToPrimaryMeasureWeightAsync when converting a value TO the base weight FROM a source MeasureWeight whose Ratio is 0 (decimal.Zero). nopCommerce divides by Ratio, so a zero source ratio would produce a wrong result; it aborts with NopException instead.","triggerScenarios":"Calling ConvertToPrimaryMeasureWeightAsync(value, sourceMeasureWeight) where sourceMeasureWeight.Ratio == 0m, sourceMeasureWeight.Id != BaseWeightId, and value != 0m. Reached via ConvertMeasureWeightAsync (the public weight-conversion entry point at line 318) or directly.","commonSituations":"Product weight stored in a unit whose MeasureWeight row has Ratio 0 (newly added unit, sample-data gap, or migration that cleared ratios); admin changed the base weight unit without re-keying all other units; custom import created weight records without ratios.","solutions":["In Configuration > Measures > Weights, set a non-zero Ratio on the source weight unit named in the error.","Verify BaseWeightId points to an existing configured weight so the source-vs-base comparison at line 369 is meaningful.","Guard the caller: only invoke conversion when sourceMeasureWeight.Ratio != decimal.Zero.","If migrating data, run a one-time script asserting every published MeasureWeight has Ratio != 0 before enabling the store."],"exampleFix":"// before\nvar baseWeight = await _measureService.ConvertToPrimaryMeasureWeightAsync(productWeight, sourceWeight);\n\n// after — validate the source ratio first\nif (productWeight != decimal.Zero && sourceWeight.Id != baseWeightId && sourceWeight.Ratio == decimal.Zero)\n    throw new InvalidOperationException($\"Source weight '{sourceWeight.Name}' has no ratio.\");\nvar baseWeight = await _measureService.ConvertToPrimaryMeasureWeightAsync(productWeight, sourceWeight);","handlingStrategy":"validation","validationCode":"// Validate before converting a source weight to the base weight\nvar baseWt = await _measureService.GetMeasureWeightByIdAsync(_measureSettings.BaseWeightId);\nif (value != decimal.Zero && sourceMeasureWeight.Id != baseWt.Id && sourceMeasureWeight.Ratio == decimal.Zero)\n    throw new InvalidOperationException($\"Configure a non-zero Ratio for weight '{sourceMeasureWeight.Name}'.\");\nvar converted = await _measureService.ConvertToPrimaryMeasureWeightAsync(value, sourceMeasureWeight);","typeGuard":"static bool IsSourceWeightConvertible(MeasureWeight source, MeasureWeight baseWt, decimal value)\n    => value == decimal.Zero || source.Id == baseWt.Id || source.Ratio != decimal.Zero;","tryCatchPattern":"try { result = await _measureService.ConvertToPrimaryMeasureWeightAsync(value, srcWt); }\ncatch (NopException ex) when (ex.Message.StartsWith(\"Exchange ratio not set for weight\"))\n{ /* surface 'configure the source weight ratio'; never substitute zero */ }","preventionTips":["Require Ratio on every weight unit in seed data.","Validate product.Weight + its MeasureWeight ratio before any display/shipping calculation.","Add a migration-time assertion that no published weight has Ratio == 0."],"tags":["measure","weight","configuration","nopcommerce"],"backgroundTag":null,"analyzedSha":"64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2","analyzedAt":"2026-08-13T21:19:38.062Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}