nopSolutions/nopCommerce · error · NopException
Capture ID not set
Error message
Capture ID not set
What it means
Thrown by RefundAsync when nopOrder.CaptureTransactionId is null or empty. A refund targets a specific captured payment, so PayPal requires the capture resource id; without it the CreateRefundRequest.CaptureId cannot be set. This guard fires before any API call and is surfaced as the Error string.
Source
Thrown at src/Plugins/Nop.Plugin.Payments.PayPalCommerce/Services/PayPalCommerceServiceManager.cs:2566
/// <param name="nopOrder">Order</param>
/// <param name="amount">Amount to refund; pass null to refund the full captured amount</param>
/// <returns>
/// A task that represents the asynchronous operation
/// The task result contains the refund details; error message if exists
/// </returns>
public async Task<(Refund Refund, string Error)> RefundAsync(PayPalCommerceSettings settings, NopOrder nopOrder, decimal? amount = null)
{
return await HandleFunctionAsync(async () =>
{
if (!IsConfigured(settings))
throw new NopException("Plugin not configured");
var currencyCode = (await _currencyService.GetCurrencyByIdAsync(_currencySettings.PrimaryStoreCurrencyId))?.CurrencyCode;
if (string.IsNullOrEmpty(currencyCode))
throw new NopException("Primary store currency not set");
if (string.IsNullOrEmpty(nopOrder.CaptureTransactionId))
throw new NopException("Capture ID not set");
var request = new CreateRefundRequest
{
CaptureId = nopOrder.CaptureTransactionId,
Amount = amount.HasValue ? PrepareMoney(amount.Value, currencyCode) : null
};
var refund = await _httpClient.RequestAsync<CreateRefundRequest, CreateRefundResponse>(request, settings);
if (refund.Status?.ToUpper() == RefundStatusType.CANCELLED.ToString())
throw new NopException("The refund was cancelled");
if (refund.Status?.ToUpper() == RefundStatusType.FAILED.ToString())
throw new NopException("The refund could not be processed");
if (refund.Status?.ToUpper() == RefundStatusType.PENDING.ToString())
throw new NopException($"Capture is in {refund.Status} status due to {refund.StatusDetails?.Reason}");
//save id to avoid double refundView on GitHub (pinned to 64bdf2ff08)
Solutions
- Confirm the order was actually captured and that order.CaptureTransactionId is populated.
- Guard with !string.IsNullOrEmpty(nopOrder.CaptureTransactionId) before calling RefundAsync.
- If the order is Authorize-only, void it (VoidAsync) instead of refunding.
Example fix
// before
var (refund, err) = await _serviceManager.RefundAsync(settings, order, amount);
// after
if (string.IsNullOrEmpty(order.CaptureTransactionId))
{
NotifyError("Order has no captured payment to refund");
return;
}
var (refund, err) = await _serviceManager.RefundAsync(settings, order, amount); Defensive patterns
Strategy: validation
Validate before calling
if (string.IsNullOrEmpty(order.CaptureTransactionId))
return; // no capture to refund Type guard
static string CaptureId(NopOrder o) =>
string.IsNullOrEmpty(o?.CaptureTransactionId) ? null : o.CaptureTransactionId; Try / catch
var (refund, error) = await mgr.RefundAsync(settings, order, amount);
if (!string.IsNullOrEmpty(error))
NotifyError(error); Prevention
- Show Refund only when CaptureTransactionId is set; show Void for authorize-only orders.
- Confirm the capture step persisted the id before enabling refunds.
- Do not refund orders placed via other payment methods.
When it happens
Trigger: Refunding an order that was authorized but never captured; the capture step ran but failed to persist CaptureTransactionId on the order; attempting to refund a manually-created or Authorize-only order.
Common situations: Payment mode set to Authorize (not Capture), so there is no capture to refund; capture failed mid-flow and the order was left without a capture id; order was placed through a different payment method and CaptureTransactionId was never set.
Related errors
- The refund was cancelled
- The refund could not be processed
- Capture is in {refund.Status} status due to {refund.StatusDe
- Shopping cart has no recurring items
- Setup token not set
AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13).
Data as JSON: /api/errors/439034809cbcaf9a.
Report an issue: GitHub.