nopSolutions/nopCommerce · error · NopException
Setup token not set
Error message
Setup token not set
What it means
Thrown by CreateRecurringOrderAsync when the setupTokenId argument is null or empty. The recurring order is built from an approved setup token (the payer authenticated it), so the token id is required to create the payment token. This guard fires before cart preparation and is returned as the Error string.
Source
Thrown at src/Plugins/Nop.Plugin.Payments.PayPalCommerce/Services/PayPalCommerceServiceManager.cs:2713
/// <returns>
/// A task that represents the asynchronous operation
/// The task result contains the created order; error message if exists
/// </returns>
public async Task<(Order Order, string Error)> CreateRecurringOrderAsync(PayPalCommerceSettings settings, string setupTokenId)
{
return await HandleFunctionAsync(async () =>
{
if (!IsConfigured(settings))
throw new NopException("Plugin not configured");
if (string.IsNullOrEmpty(settings.MerchantId))
throw new NopException("Merchant PayPal ID not set");
if (!settings.UseVault)
throw new NopException("Vault disabled");
if (string.IsNullOrEmpty(setupTokenId))
throw new NopException("Setup token not set");
var details = await PrepareCartDetailsAsync(ButtonPlacement.PaymentMethod);
if (!await _shoppingCartService.ShoppingCartIsRecurringAsync(details.Cart))
throw new NopException("Shopping cart has no recurring items");
if (await _customerService.IsGuestAsync(details.Customer))
throw new NopException("Anonymous checkout disabled for recurring items");
//try to create payment token by the approved setup token
var payer = await PrepareBillingDetailsAsync(settings, details);
var paymentTokenRequest = new CreatePaymentTokenRequest
{
Customer = payer,
PaymentSource = new()
{
Token = new()
{View on GitHub (pinned to 64bdf2ff08)
Solutions
- Pass the setup token id returned/recorded from the setup-token approval step into CreateRecurringOrderAsync.
- Validate !string.IsNullOrEmpty(setupTokenId) before the call and re-prompt/abort if missing.
- Ensure the approval callback persists setupTokenId (e.g. in order generic attributes or session) before invoking order creation.
Example fix
// before
var (order, err) = await _serviceManager.CreateRecurringOrderAsync(settings, setupTokenId);
// after
if (string.IsNullOrEmpty(setupTokenId))
{
NotifyError("Missing approved setup token; restart the recurring payment flow");
return;
}
var (order, err) = await _serviceManager.CreateRecurringOrderAsync(settings, setupTokenId); Defensive patterns
Strategy: validation
Validate before calling
if (string.IsNullOrEmpty(setupTokenId))
return; Type guard
static string SetupToken(string id) => string.IsNullOrEmpty(id) ? null : id;
Try / catch
var (order, error) = await mgr.CreateRecurringOrderAsync(settings, setupTokenId);
if (!string.IsNullOrEmpty(error))
NotifyError(error); Prevention
- Persist the approved setup token id through the approval callback/session.
- Validate setupTokenId before calling order creation.
- Restart the setup-token flow if the id is missing.
When it happens
Trigger: Calling CreateRecurringOrderAsync without the setup token id; the setup-token approval callback did not pass the token id forward; the token id was lost between the approval redirect and the order-creation step.
Common situations: Payer approved the setup token but the return URL/session did not carry setupTokenId; integration wired the wrong query/attribute name; approval webhook handled but id not persisted.
Related errors
- Shopping cart has no recurring items
- {error}
- Capture ID not set
- Payment token not created
- Vault disabled
AI-assisted analysis of nopSolutions/nopCommerce@64bdf2ff08 (2026-08-13).
Data as JSON: /api/errors/a1eff1af5fb7442f.
Report an issue: GitHub.