nopSolutions/nopCommerce · error · ArgumentException

No recurring payment found with the specified id

Error message

No recurring payment found with the specified id

What it means

Thrown by HistoryList (POST, RECURRING_PAYMENTS_VIEW) on RecurringPaymentController when GetRecurringPaymentByIdAsync(searchModel.RecurringPaymentId) returns null. The action assembles the recurring-payment history list, which requires the parent payment, so a missing record aborts before the model factory.

Source

Thrown at src/Presentation/Nop.Web/Areas/Admin/Controllers/RecurringPaymentController.cs:138

        //try to get a recurring payment with the specified id
        var payment = await _orderService.GetRecurringPaymentByIdAsync(id);
        if (payment == null)
            return RedirectToAction("List");

        await _orderService.DeleteRecurringPaymentAsync(payment);

        _notificationService.SuccessNotification(await _localizationService.GetResourceAsync("Admin.RecurringPayments.Deleted"));

        return RedirectToAction("List");
    }

    [HttpPost]
    [CheckPermission(StandardPermission.Orders.RECURRING_PAYMENTS_VIEW)]
    public virtual async Task<IActionResult> HistoryList(RecurringPaymentHistorySearchModel searchModel)
    {
        //try to get a recurring payment with the specified id
        var payment = await _orderService.GetRecurringPaymentByIdAsync(searchModel.RecurringPaymentId)
                      ?? throw new ArgumentException("No recurring payment found with the specified id");

        //prepare model
        var model = await _recurringPaymentModelFactory.PrepareRecurringPaymentHistoryListModelAsync(searchModel, payment);

        return Json(model);
    }

    [HttpPost, ActionName("Edit")]
    [FormValueRequired("processnextpayment")]
    [CheckPermission(StandardPermission.Orders.RECURRING_PAYMENTS_CREATE_EDIT_DELETE)]
    public virtual async Task<IActionResult> ProcessNextPayment(int id)
    {
        //try to get a recurring payment with the specified id
        var payment = await _orderService.GetRecurringPaymentByIdAsync(id);
        if (payment == null)
            return RedirectToAction("List");

        try

View on GitHub (pinned to 64bdf2ff08)

Solutions

  1. Reopen the recurring-payments list and select a current payment to view history.
  2. Return an empty grid when the payment is missing rather than 500.
  3. Validate searchModel.RecurringPaymentId > 0 before requesting.
  4. Avoid cancelling/deleting payments while their history tab is loading.

Example fix

// before
var payment = await _orderService.GetRecurringPaymentByIdAsync(searchModel.RecurringPaymentId)
              ?? throw new ArgumentException("No recurring payment found with the specified id");

// after
var payment = await _orderService.GetRecurringPaymentByIdAsync(searchModel.RecurringPaymentId);
if (payment == null)
    return Json(new { Data = Enumerable.Empty<object>(), Total = 0 });
Defensive patterns

Strategy: validation

Validate before calling

if (searchModel.RecurringPaymentId <= 0) return Json(empty);
var payment = await _orderService.GetRecurringPaymentByIdAsync(searchModel.RecurringPaymentId);
if (payment == null) return Json(empty);

Type guard

// N/A

Try / catch

catch (ArgumentException ex) when (ex.Message.Contains("No recurring payment"))
{ return Json(new { Data = Array.Empty<object>(), Total = 0 }); }

Prevention

When it happens

Trigger: The history sub-grid for a recurring payment whose id is stale, deleted, or forged; payment removed by a cancellation/cleanup job between page load and sub-grid load; tampered RecurringPaymentId.

Common situations: Recurring payment deleted/expired while the detail page is open; restored DBs; fixtures; URLs from cached pages.

Related errors


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