nopSolutions/nopCommerce · error · NopException

You can't mark this order as paid

Error message

You can't mark this order as paid

What it means

Thrown by OrderProcessingService.MarkOrderAsPaidAsync when CanMarkOrderAsPaid(order) returns false. The order cannot be marked paid if OrderStatus == Cancelled, or if PaymentStatus is already Paid, Refunded, or Voided. It prevents an admin from manually marking an order paid when it is in a terminal/cancelled payment state.

Source

Thrown at src/Libraries/Nop.Services/Orders/OrderProcessingService.cs:2590

        if (order.PaymentStatus == PaymentStatus.Paid ||
            order.PaymentStatus == PaymentStatus.Refunded ||
            order.PaymentStatus == PaymentStatus.Voided)
            return false;

        return true;
    }

    /// <summary>
    /// Marks order as paid
    /// </summary>
    /// <param name="order">Order</param>
    /// <returns>A task that represents the asynchronous operation</returns>
    public virtual async Task MarkOrderAsPaidAsync(Order order)
    {
        ArgumentNullException.ThrowIfNull(order);

        if (!CanMarkOrderAsPaid(order))
            throw new NopException("You can't mark this order as paid");

        order.PaymentStatusId = (int)PaymentStatus.Paid;
        order.PaidDateUtc = DateTime.UtcNow;
        await _orderService.UpdateOrderAsync(order);

        //add a note
        await AddOrderNoteAsync(order, "Order has been marked as paid");

        await CheckOrderStatusAsync(order);

        if (order.PaymentStatus == PaymentStatus.Paid)
            await ProcessOrderPaidAsync(order);
    }

    /// <summary>
    /// Gets a value indicating whether refund from admin panel is allowed
    /// </summary>
    /// <param name="order">Order</param>

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Guard with the helper: if (!_orderProcessingService.CanMarkOrderAsPaid(order)) return; or check status before calling.
  2. Make the mark-paid endpoint idempotent and disable the UI action when PaymentStatus == Paid.
  3. If the order was wrongly cancelled, investigate the cancel flow before marking paid rather than forcing payment.
  4. Ensure integrations only call MarkOrderAsPaidAsync for orders in Pending payment status.

Example fix

// before
await _orderProcessingService.MarkOrderAsPaidAsync(order);

// after
if (!_orderProcessingService.CanMarkOrderAsPaid(order))
    return;

await _orderProcessingService.MarkOrderAsPaidAsync(order);
Defensive patterns

Strategy: validation

Validate before calling

if (!_orderProcessingService.CanMarkOrderAsPaid(order))
    return;

await _orderProcessingService.MarkOrderAsPaidAsync(order);

Prevention

When it happens

Trigger: Calling MarkOrderAsPaidAsync when order is Cancelled, or when PaymentStatus is Paid, Refunded, or Voided. Happens on duplicate 'Mark as paid' actions, marking paid a cancelled order, or marking paid an order that a refund/void already settled.

Common situations: Admin double-clicking 'Mark as paid'; an integration re-firing the paid event; attempting to mark paid an order that was refunded offline; marking paid a cancelled order.

Related errors


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