{"record":{"id":"e69e05eabe58a761","repo":"nopSolutions/nopCommerce","slug":"you-can-t-refund-this-order","errorCode":null,"errorMessage":"You can't refund this order","messagePattern":"You can't refund this order","errorType":"exception","errorClass":"NopException","httpStatus":null,"severity":"error","filePath":"src/Libraries/Nop.Services/Orders/OrderProcessingService.cs","lineNumber":2751,"sourceCode":"        //     return false;\r\n\r\n        if (order.PaymentStatus == PaymentStatus.Paid)\r\n            return true;\r\n\r\n        return false;\r\n    }\r\n\r\n    /// <summary>\r\n    /// Refunds an order (offline)\r\n    /// </summary>\r\n    /// <param name=\"order\">Order</param>\r\n    /// <returns>A task that represents the asynchronous operation</returns>\r\n    public virtual async Task RefundOfflineAsync(Order order)\r\n    {\r\n        ArgumentNullException.ThrowIfNull(order);\r\n\r\n        if (!CanRefundOffline(order))\r\n            throw new NopException(\"You can't refund this order\");\r\n\r\n        //amout to refund\r\n        var amountToRefund = order.OrderTotal;\r\n\r\n        //total amount refunded\r\n        var totalAmountRefunded = order.RefundedAmount + amountToRefund;\r\n\r\n        //update order info\r\n        order.RefundedAmount = totalAmountRefunded;\r\n        order.PaymentStatus = PaymentStatus.Refunded;\r\n        await _orderService.UpdateOrderAsync(order);\r\n\r\n        //add a note\r\n        await AddOrderNoteAsync(order, $\"Order has been marked as refunded. Amount = {amountToRefund}\");\r\n\r\n        //raise event       \r\n        await _eventPublisher.PublishAsync(new OrderRefundedEvent(order, amountToRefund));\r\n\r","sourceCodeStart":2733,"sourceCodeEnd":2769,"githubUrl":"https://github.com/nopSolutions/nopCommerce/blob/64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2/src/Libraries/Nop.Services/Orders/OrderProcessingService.cs#L2733-L2769","documentation":"Thrown by OrderProcessingService.RefundOfflineAsync when CanRefundOffline(order) returns false. An offline (manual) full refund is allowed only when OrderTotal > 0, RefundedAmount == 0 (no prior partial refunds), and PaymentStatus == Paid. Offline refunds bypass the payment gateway, so the order must be Paid and not already partially refunded.","triggerScenarios":"Calling RefundOfflineAsync when: OrderTotal == 0; RefundedAmount > 0; or PaymentStatus != Paid. Common when an admin tries an offline refund on an order that is not Paid or that was already partially refunded.","commonSituations":"Order still Pending or Authorized (not Paid); a partial refund already applied (use PartiallyRefundOfflineAsync); zero-total order; staff using offline refund because the gateway refund failed but the order is not in Paid state.","solutions":["Guard with: if (!_orderProcessingService.CanRefundOffline(order)) return; and report the reason.","If RefundedAmount > 0, use PartiallyRefundOfflineAsync(order, remaining) instead.","Confirm PaymentStatus == Paid before showing the offline refund action.","For free/zero-total orders, no refund is needed."],"exampleFix":"// before\nawait _orderProcessingService.RefundOfflineAsync(order);\n\n// after\nif (!_orderProcessingService.CanRefundOffline(order))\n    return;\n\nawait _orderProcessingService.RefundOfflineAsync(order);","handlingStrategy":"validation","validationCode":"if (!_orderProcessingService.CanRefundOffline(order))\n    return;\n\nawait _orderProcessingService.RefundOfflineAsync(order);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["If RefundedAmount > 0, use PartiallyRefundOfflineAsync.","Confirm PaymentStatus == Paid before offering offline refund.","Skip for zero-total orders."],"tags":["refund","offline","payment","order-processing"],"backgroundTag":null,"analyzedSha":"64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2","analyzedAt":"2026-08-13T21:19:38.062Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}