title: Uncaught (in promise) IntegrationError: Missing value for Stripe(): apiKey should be a string. Only while deployed to vercel but working fine on local
body: <p>My stripe checkout session on my localhost is working fine, but when I try to redirect from my deployed website's checkout page, there is an ERROR.</p>
  <p><a href="https://i.stack.imgur.com/wVhm2.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/wVhm2.png" alt="enter image description here" /></a></p>
  <p>My code where I think the error is coming from:</p>
  <p><code>/src/pages/checkout.js</code></p>
  <pre><code>import { useSession } from &quot;next-auth/client&quot;;
  import Image from &quot;next/image&quot;;
  import { useSelector } from &quot;react-redux&quot;;
  import CheckoutProduct from &quot;../components/CheckoutProduct&quot;;
  import Header from &quot;../components/Header&quot;;
  import Currency from &quot;react-currency-formatter&quot;;
  import { selectItems, selectTotal } from &quot;../slices/basketSlice&quot;;
  import { loadStripe } from &quot;@stripe/stripe-js&quot;;
  import axios from &quot;axios&quot;;
  
  const stripePromise = loadStripe(process.env.stripe_public_key);
  
  function checkout() {
    const items = useSelector(selectItems);
    const total = useSelector(selectTotal);
    const [session] = useSession();
  
    const createCheckoutSession = async () =&gt; {
      const stripe = await stripePromise;
  
      // call the backend to create a checkout session
      const checkoutSession = await axios.post(&quot;/api/create-checkout-session&quot;, {
        items: items,
        email: session.user.email,
      });
      // redirect customers to stripe checkout
      const result = await stripe.redirectToCheckout({
        sessionId: checkoutSession.data.id,
      });
      if (result.error) {
        alert(result.error.message);
      }
    };
  
    return (
      &lt;div className=&quot;h-screen&quot;&gt;
        &lt;Header /&gt;
        &lt;main className=&quot;lg:flex flex-1 overflow-y-auto max-w-screen-2xl mx-auto&quot;&gt;
          {/* Left side */}
          &lt;div className=&quot;flex-grow m-5 shadow-sm&quot;&gt;
            &lt;Image
              src=&quot;/images/amazon-cart.jpg&quot;
              width={1020}
              height={250}
              objectFit=&quot;contain&quot;
            /&gt;
            &lt;div className=&quot;fex flex-col p-5 space-y-10 bg-white&quot;&gt;
              &lt;h1 className=&quot;text-3xl border-b pb-4&quot;&gt;
                {items.length === 0
                  ? &quot;Your Amazon basket is empty&quot;
                  : &quot;Shopping Basket&quot;}
              &lt;/h1&gt;
              {items.map((item, i) =&gt; (
                &lt;CheckoutProduct
                  key={i}
                  id={item.id}
                  title={item.title}
                  rating={item.rating}
                  price={item.price}
                  description={item.description}
                  category={item.category}
                  image={item.image}
                  hasPrime={item.hasPrime}
                /&gt;
              ))}
            &lt;/div&gt;
          &lt;/div&gt;
  
          {/* Right side */}
          &lt;div className=&quot;flex flex-col bg-white p-10 shadow-md&quot;&gt;
            {items.length &gt; 0 &amp;&amp; (
              &lt;&gt;
                &lt;h2 className=&quot;whitespace-nowrap&quot;&gt;
                  Subtotal ({items.length} items):
                  &lt;span className=&quot;font-bold&quot;&gt;
                    &lt;Currency quantity={total} currency=&quot;EUR&quot; /&gt;
                  &lt;/span&gt;
                &lt;/h2&gt;
                &lt;button
                  role=&quot;link&quot;
                  onClick={createCheckoutSession}
                  disabled={!session}
                  className={`button mt-2 ${
                    !session &amp;&amp;
                    &quot;from-gray-300 to-gray-500 border-gray-200 text-gray-300 cursor-not-allowed&quot;
                  }`}
                &gt;
                  {!session ? &quot;Sign in to Checkout&quot; : &quot;Proceed to Checkout&quot;}
                &lt;/button&gt;
              &lt;/&gt;
            )}
          &lt;/div&gt;
        &lt;/main&gt;
      &lt;/div&gt;
    );
  }
  
  export default checkout;
  </code></pre>
  <p><code>/next.config.js</code></p>
  <pre><code>module.exports = {
  
    env: {
      stripe_public_key: process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY,
    },
  };
  </code></pre>
  <p>My environment variables are also deployed on Vercel with the below naming convention:</p>
  <pre><code>NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_mykey
  
  # Stripe Terminal/CLI
  STRIPE_WEBHOOK_SECRET=whsec_mywebhooksecret
  
  STRIPE_SECRET_KEY=sk_test_mysecret
  </code></pre>
  <p><code>/src/pages/api/create-checkout-session.js</code></p>
  <pre><code>const stripe = require(&quot;stripe&quot;)(process.env.STRIPE_SECRET_KEY);
  
  export default async (req, res) =&gt; {
    const { items, email } = req.body;
    //   console.log(items);
    //   console.log(email);
    const transformedItems = items.map((item) =&gt; ({
      price_data: {
        currency: &quot;eur&quot;,
        product_data: {
          name: item.title,
          images: [item.image],
        },
        unit_amount: item.price * 100,
      },
      description: item.description,
      quantity: 1,
    }));
  
    const session = await stripe.checkout.sessions.create({
      payment_method_types: [&quot;card&quot;],
      shipping_rates: [&quot;shr_1JPZN2HHQ2qhqkUCKLyMJDLO&quot;],
      shipping_address_collection: {
        allowed_countries: [&quot;GB&quot;, &quot;US&quot;, &quot;CA&quot;, &quot;DE&quot;],
      },
      line_items: transformedItems,
      mode: &quot;payment&quot;,
      success_url: `${process.env.HOST}/success`,
      cancel_url: `${process.env.HOST}/checkout`,
      metadata: {
        email,
        images: JSON.stringify(items.map((item) =&gt; item.image)),
      },
    });
  
    res.status(200).json({ id: session.id });
  };
  </code></pre>
  <p><code>/src/pages/api/webhook.js</code></p>
  <pre><code>import { buffer } from &quot;micro&quot;;
  import * as admin from &quot;firebase-admin&quot;;
  
  // secure a connection to FIREBASE from backend
  const serviceAccount = require(&quot;../../../permissions.json&quot;);
  
  const app = !admin.apps.length
    ? admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
      })
    : admin.app();
  
  //   Establish connection to stripe
  const stripe = require(&quot;stripe&quot;)(process.env.STRIPE_SECRET_KEY);
  
  const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET;
  
  const fullfillOrder = async (session) =&gt; {
    //console.log(&quot;Fulfilling order&quot;, session);
  
    return app
      .firestore()
      .collection(&quot;users&quot;)
      .doc(session.metadata.email)
      .collection(&quot;orders&quot;)
      .doc(session.id)
      .set({
        amount: session.amount_total / 100,
        amount_shipping: session.total_details.amount_shipping / 100,
        images: JSON.parse(session.metadata.images),
        timestamp: admin.firestore.FieldValue.serverTimestamp(),
        customer_email: session.customer_details.email,
      })
      .then(() =&gt; {
        console.log(`SUCCESS: Order ${session.id} has been added to DB`);
      });
  };
  
  export default async (req, res) =&gt; {
    if (req.method === &quot;POST&quot;) {
      const requestBuffer = await buffer(req);
      const payload = requestBuffer.toString();
      const sig = req.headers[&quot;stripe-signature&quot;];
      let event;
      //   verify that the event posted came from stripe
      try {
        event = stripe.webhooks.constructEvent(payload, sig, endpointSecret);
      } catch (error) {
        console.log(&quot;ERROR while constructing event&quot;, error.message);
        return res
          .status(400)
          .send(`Webhook error while constructing event:${error.message}`);
      }
  
      // Handle checkout.session.completed event
      if (event.type === &quot;checkout.session.completed&quot;) {
        const session = event.data.object;
  
        //   fulfill the order...
        return fullfillOrder(session)
          .then(() =&gt; res.status(200))
          .catch((err) =&gt; {
            console.log(&quot;ERROR while fulfilling order&quot;, err.message);
            res
              .status(400)
              .send(`Webhook Error while fulfilling order: ${err.message}`);
          });
      }
    }
  };
  
  export const config = {
    api: {
      bodyParser: false,
      externalResolver: true,
    },
  };
  </code></pre>
  <p>The app is hosted on Vercel. Created with Next.js / React / Redux. Connected to Firebase / Stripe and I use Axios.</p>
  <p>Is this snippet of code where the error is coming from? The hardest part about understanding this error is my app works perfectly fine in the localhost with zero issues on all pages in the console, but on the deployed website this error comes up.</p>
  <p>What part of my code might be wrong? I want to be able to click the button and be taken to the Stripe checkout page.</p>