nopSolutions/nopCommerce · warning · NopException

Enter amount to refund

Error message

Enter amount to refund

What it means

Thrown in the OrderController partial-refund action when model.AmountToRefund is less than or equal to decimal.Zero. The action then clamps the amount to the maximum refundable (order total minus already-refunded), so a non-positive amount is treated as user input error rather than a partial refund. NopException, caught and shown as an error notification.

Source

Thrown at src/Presentation/Nop.Web/Areas/Admin/Controllers/OrderController.cs:820

    [HttpPost]
    [FormValueRequired("partialrefundorder")]
    [CheckPermission(StandardPermission.Orders.ORDERS_CREATE_EDIT_DELETE)]
    public virtual async Task<IActionResult> PartiallyRefundOrderPopup(int id, bool online, OrderModel model)
    {
        //try to get an order with the specified id
        var order = await _orderService.GetOrderByIdAsync(id);
        if (order == null)
            return RedirectToAction("List");

        //a vendor does not have access to this functionality
        if (await _workContext.GetCurrentVendorAsync() != null)
            return RedirectToAction("Edit", new { id = order.Id });

        try
        {
            var amountToRefund = model.AmountToRefund;
            if (amountToRefund <= decimal.Zero)
                throw new NopException("Enter amount to refund");

            var maxAmountToRefund = order.OrderTotal - order.RefundedAmount;
            if (amountToRefund > maxAmountToRefund)
                amountToRefund = maxAmountToRefund;

            var errors = new List<string>();
            if (online)
                errors = (await _orderProcessingService.PartiallyRefundAsync(order, amountToRefund)).ToList();
            else
                await _orderProcessingService.PartiallyRefundOfflineAsync(order, amountToRefund);

            await LogEditOrderAsync(order.Id);

            if (!errors.Any())
            {
                //success
                ViewBag.RefreshPage = true;

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Enter a positive refund amount not exceeding (OrderTotal - RefundedAmount).
  2. Check the amount field's number formatting matches the server culture (decimal separator).
  3. Add client-side validation requiring a positive number before submit.
  4. If the full order is already refunded, the maxAmountToRefund will be 0 — inform the admin rather than allowing submit.

Example fix

// before
var amountToRefund = model.AmountToRefund;
if (amountToRefund <= decimal.Zero)
    throw new NopException("Enter amount to refund");

// after — guard with a friendly notification and clamp hint
var maxAmountToRefund = order.OrderTotal - order.RefundedAmount;
if (model.AmountToRefund <= decimal.Zero || model.AmountToRefund > maxAmountToRefund)
{
    _notificationService.ErrorNotification($"Enter an amount between 0.01 and {maxAmountToRefund}.");
    return RedirectToAction("Edit", new { id = order.Id });
}
Defensive patterns

Strategy: validation

Validate before calling

// Before refunding: validate the amount against the refundable ceiling
var maxRefund = order.OrderTotal - order.RefundedAmount;
if (model.AmountToRefund <= decimal.Zero || model.AmountToRefund > maxRefund)
{
    _notificationService.ErrorNotification($"Enter a refund amount between 0.01 and {maxRefund}.");
    return RedirectToAction("Edit", new { id = order.Id });
}

Type guard

bool IsValidRefundAmount(decimal amount, Order order) => amount > decimal.Zero && amount <= (order.OrderTotal - order.RefundedAmount);

Try / catch

// The action's try/catch shows exc.Message; pre-validate the amount client-side and server-side.

Prevention

When it happens

Trigger: POST to the partial refund (online or offline) endpoint with AmountToRefund of 0, a negative number, or an empty/non-numeric value that binds to 0.

Common situations: The admin leaves the refund amount field blank (binds to 0); a localized number format (comma vs dot decimal separator) fails model binding and defaults to 0; the refund form is submitted without selecting an amount.

Related errors


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