# How to fix currency mismatch error in Stripe

- Tool: Stripe
- Difficulty: Beginner
- Time required: 10 minutes
- Compatibility: Stripe API v2024-12+, Node.js 18+
- Last updated: March 2026

## TL;DR

Stripe returns a currency mismatch error when you try to charge a customer or pay an invoice in a different currency than the one specified on the object. This commonly happens when creating a PaymentIntent without specifying a currency, using a price in one currency but charging in another, or mixing currencies within a single customer. Always pass the currency parameter explicitly and keep it consistent.

## Why Currency Mismatch Errors Happen in Stripe

Stripe requires consistent currency usage across related objects. If you create a price in EUR but try to create a PaymentIntent in USD for that price, Stripe rejects it. Similarly, a customer's default currency (set by their first charge) may conflict with subsequent charges in different currencies. The fix is straightforward: always explicitly specify the currency parameter and ensure it matches across your prices, invoices, and payment intents.

## Before you start

- A Stripe account in test mode
- Node.js 18+ with the Stripe npm package
- At least one product and price created in the Stripe Dashboard

## Step-by-step guide

### 1. Understand how Stripe assigns currencies

Every Stripe price has a fixed currency set at creation. When you create a PaymentIntent, you must specify a currency. If these don't match — for example, a USD price charged in EUR — Stripe returns a currency mismatch error. Amounts are always in the smallest currency unit (cents for USD, pennies for GBP).

**Expected result:** You understand that currencies are set at the price level and must be consistent across all related Stripe objects.

### 2. Always pass the currency parameter explicitly

Never rely on defaults. Explicitly set the currency when creating PaymentIntents, charges, or invoices. This prevents surprises when your account's default currency differs from what you intend.

```
// CORRECT — explicit currency
const paymentIntent = await stripe.paymentIntents.create({
  amount: 2000,       // $20.00 in cents
  currency: 'usd',   // Always specify!
  automatic_payment_methods: { enabled: true },
});

// WRONG — missing currency leads to account default
const paymentIntent = await stripe.paymentIntents.create({
  amount: 2000,
  // currency not specified — uses account default, which may not be what you want
});
```

**Expected result:** PaymentIntents are created with an explicit currency that matches your prices.

### 3. Match the currency to your Stripe price

When charging for a specific product, retrieve the price first and use its currency to create the PaymentIntent. This ensures the amounts and currency are always in sync.

```
async function createPaymentForPrice(priceId) {
  // Fetch the price to get its currency and unit_amount
  const price = await stripe.prices.retrieve(priceId);

  const paymentIntent = await stripe.paymentIntents.create({
    amount: price.unit_amount,     // Use the price's amount
    currency: price.currency,      // Use the price's currency
    metadata: { price_id: priceId },
    automatic_payment_methods: { enabled: true },
  });

  return paymentIntent;
}
```

**Expected result:** The PaymentIntent currency always matches the price currency, eliminating mismatch errors.

### 4. Handle multi-currency products

If you sell in multiple currencies, create separate prices for each currency on the same product. Then select the correct price based on the customer's currency preference.

```
// Create prices for different currencies on the same product
const usdPrice = await stripe.prices.create({
  product: 'prod_ABC123',
  unit_amount: 2000,    // $20.00
  currency: 'usd',
});

const eurPrice = await stripe.prices.create({
  product: 'prod_ABC123',
  unit_amount: 1800,    // 18.00 EUR
  currency: 'eur',
});

// Select the right price based on customer's currency
function getPriceForCurrency(currency) {
  const priceMap = {
    usd: 'price_usd_id',
    eur: 'price_eur_id',
  };
  return priceMap[currency] || priceMap.usd;
}
```

**Expected result:** Each currency has its own price object, and you select the correct one based on the customer's preference.

## Complete code example

File: `currency-handler.js`

```javascript
require('dotenv').config();
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

// Supported currencies and their price IDs
const PRICE_MAP = {
  usd: process.env.PRICE_USD,
  eur: process.env.PRICE_EUR,
  gbp: process.env.PRICE_GBP,
};

const SUPPORTED_CURRENCIES = Object.keys(PRICE_MAP);

async function createPaymentIntent(currency, priceId) {
  // Validate currency
  const normalizedCurrency = currency.toLowerCase();
  if (!SUPPORTED_CURRENCIES.includes(normalizedCurrency)) {
    throw new Error(
      `Unsupported currency: ${currency}. Supported: ${SUPPORTED_CURRENCIES.join(', ')}`
    );
  }

  // Fetch price to ensure currency matches
  const price = await stripe.prices.retrieve(priceId || PRICE_MAP[normalizedCurrency]);

  if (price.currency !== normalizedCurrency) {
    throw new Error(
      `Currency mismatch: price is in ${price.currency} but ${normalizedCurrency} was requested`
    );
  }

  const paymentIntent = await stripe.paymentIntents.create({
    amount: price.unit_amount,
    currency: price.currency,
    metadata: {
      price_id: price.id,
      product_id: price.product,
    },
    automatic_payment_methods: { enabled: true },
  });

  return paymentIntent;
}

module.exports = { createPaymentIntent, SUPPORTED_CURRENCIES };
```

## Common mistakes

- **Omitting the currency parameter and relying on account defaults** — undefined Fix: Always explicitly pass the currency parameter when creating PaymentIntents, charges, or invoice items. Account defaults may not match your intended currency.
- **Using a price in one currency and creating a PaymentIntent in another** — undefined Fix: Retrieve the price first and use price.currency for the PaymentIntent. Or create separate prices for each currency you support.
- **Passing amounts in dollars instead of cents** — undefined Fix: Stripe uses the smallest currency unit. For USD, pass 2000 for $20.00. For JPY (zero-decimal currency), pass 2000 for 2000 yen.
- **Mixing currencies on a single subscription** — undefined Fix: All items in a subscription must use the same currency. Create separate subscriptions if a customer needs products in different currencies.

## Best practices

- Always pass the currency parameter explicitly — never rely on defaults
- Retrieve the price object and use its currency when creating PaymentIntents
- Create separate price objects for each currency you support
- Use lowercase three-letter ISO currency codes (usd, eur, gbp)
- Remember that Stripe uses smallest currency units — cents for USD, yen for JPY
- Validate the currency on your server before calling the Stripe API
- Store the customer's preferred currency in your database for consistent billing

## Frequently asked questions

### What is a zero-decimal currency in Stripe?

Zero-decimal currencies like JPY (Japanese yen) don't use fractional units. For JPY, pass the full amount: 1000 means 1000 yen. For USD (two-decimal), pass 1000 to mean $10.00. Stripe documentation lists all zero-decimal currencies.

### Can I change the currency of an existing Stripe price?

No. Prices are immutable once created. To use a different currency, create a new price on the same product with the desired currency.

### What happens if I don't specify a currency on a PaymentIntent?

Stripe requires the currency parameter on PaymentIntents. If omitted, the API returns an error. Always pass it explicitly.

### Can a single Stripe customer have charges in multiple currencies?

Yes, but each charge or subscription must use a single consistent currency. A customer's default currency is set by their first charge, but you can charge them in different currencies for separate transactions.

### How do I handle currency conversion?

Stripe does not convert currencies automatically. If you need to display prices in the customer's local currency, use a separate exchange rate service and create Stripe prices for each supported currency.

---

Source: https://www.rapidevelopers.com/stripe-guide/how-to-fix-currency-mismatch-error-in-stripe
© RapidDev — https://www.rapidevelopers.com/stripe-guide/how-to-fix-currency-mismatch-error-in-stripe
