payloadcms/payload · error · Error

Unknown error initiating payment

Error message

Unknown error initiating payment

What it means

Thrown by the catch block at the end of Stripe initiatePayment when the caught error is not an Error instance. It is the fallback branch of error instanceof Error ? error.message : 'Unknown error initiating payment'. The original value is logged via payload.logger.error with msg 'Error initiating payment with Stripe' before the generic message is thrown, so the true cause is in the logs.

Source

Thrown at packages/plugin-ecommerce/src/payments/adapters/stripe/initiatePayment.ts:135

          stripe: {
            customerID: customer.id,
            paymentIntentID: paymentIntent.id,
          },
        },
        req,
      })

      const returnData: InitiatePaymentReturnType = {
        clientSecret: paymentIntent.client_secret || '',
        message: 'Payment initiated successfully',
        paymentIntentID: paymentIntent.id,
      }

      return returnData
    } catch (error) {
      payload.logger.error({ err: error, msg: 'Error initiating payment with Stripe' })

      throw new Error(error instanceof Error ? error.message : 'Unknown error initiating payment')
    }
  }

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Inspect the Payload log entry (msg 'Error initiating payment with Stripe', field err) for the real cause.
  2. Reproduce locally and log typeof error, error, and (error as any)?.constructor?.name.
  3. Align the stripe package version with the adapter's expectations.
  4. Normalize third-party rejections to Error objects before they reach the adapter.

Example fix

// before: dependency throws a non-Error
throw { status: 400 } // surfaces as 'Unknown error initiating payment'
// after
throw new Error('Request failed with status 400')
Defensive patterns

Strategy: try-catch

Validate before calling

// Normalize third-party rejections to Error instances before they reach the adapter
async function safeStripeCall<T>(fn: () => Promise<T>): Promise<T> {
  try {
    return await fn()
  } catch (e) {
    if (e instanceof Error) throw e
    throw new Error(typeof e === 'string' ? e : JSON.stringify(e))
  }
}

Type guard

export function isErrorLike(e: unknown): e is Error {
  return e instanceof Error || (typeof e === 'object' && e !== null && typeof (e as { message?: unknown }).message === 'string')
}

Try / catch

try {
  await payments.initiatePayment({ data })
} catch (err) {
  if (err instanceof Error && err.message === 'Unknown error initiating payment') {
    // consult server logs: msg 'Error initiating payment with Stripe' carries the original err
    return { ok: false, reason: 'unknown-initiate-error', checkLogs: true }
  }
  throw err
}

Prevention

When it happens

Trigger: Any non-Error value thrown inside initiatePayment's try block — e.g. a dependency rejecting with a string, a malformed Stripe response parsed into a plain object, or a polyfill that throws non-Error values. Error-typed throws surface their own message; only non-Error throws reach this branch.

Common situations: Stripe SDK version mismatch producing non-Error rejections; a custom middleware throwing a string; JSON.stringify failing on circular cart data and a wrapper converting it; fetch polyfills in older Node versions; misconfigured proxy throwing plain objects.

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/fe145606ac591f87. Report an issue: GitHub.