Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to load Stripe.js #26

Closed
vincentaudebert opened this issue Mar 24, 2020 · 48 comments · Fixed by #27 or #29
Closed

Failed to load Stripe.js #26

vincentaudebert opened this issue Mar 24, 2020 · 48 comments · Fixed by #27 or #29

Comments

@vincentaudebert
Copy link

vincentaudebert commented Mar 24, 2020

Summary

Some of my users are getting an error thrown Failed to load Stripe.js
Sadly, I can't reproduce and I don't have more details. My page is working perfectly fine for me and some of my colleagues.

I have js.stripe.com/v3 loaded in my head tag
And loadStripe is correctly executed only once.

Here is my code:

import { useState, useEffect } from 'react'
import { loadStripe } from '@stripe/stripe-js'

const StripeJSProvider = ({ children }) => {
  const [stripe, setStripe] = useState(false)

  useEffect(() => {
    if (!stripe) {
      setStripe(loadStripe(process.env.STRIPE_KEY))
    }
  }, [stripe])

  return children({ stripe })
}

export default StripeJSProvider

And then later:

<StripeJSProvider>
      {({ stripe }) =>
        stripe ? (
          <Elements stripe={stripe}>
            <MyComponent... />
          </Elements>
        ) : (
          <PageLoader />
        )
      }
    </StripeJSProvider>

Other information

According to sentry report, it looks like it's happening only on Firefox.

Thanks for your help.

@hofman-stripe
Copy link
Contributor

This error is raised if the script failed to load (e.g. network error), or loaded but didn't execute properly (didn't register Stripe on the global).

Do you have any CSP that might interfere with loading of the Stripe.js script? Maybe those customers have extensions installed blocking some 3rd party scripts? Do you have metrics on how often this happens? Are most Firefox users able to load without errors?

Unless you can gather more details from an impacted user, I'm not sure we'd be able to track down the cause.

@vincentaudebert
Copy link
Author

vincentaudebert commented Mar 24, 2020

It happened around 370 times to about 180 different users in 7 days.

I will try to load stripe script only when required and use window.Stripe directly instead of loadStripe() to see what happens. Will post here if it fixes the problem.

I'm suspecting extenstions too though :/

@AndrewIngram
Copy link

I'm having an issue which might be related, but I'm not getting any Stripe-related errors in Sentry. I'm just getting a lot of reports of customers not being able to type anything in the box, which suggests something is breaking when Stripe is loading.

@hofman-stripe
Copy link
Contributor

@vincentaudebert unfortunately an absolute number doesn't really tell me much about the frequency of this problem compared to successful loads. However that is a fairly high number. It would be great to see if you can find a correlation between them.

I'd still recommend you keep using loadStripe(). Maybe we can tweak the error messages to differentiate between a missing Stripe global and a script load error.

@hofman-stripe
Copy link
Contributor

@AndrewIngram, without any more information it's hard to tell.

@vincentaudebert
Copy link
Author

@hofman-stripe I reckon a different error message would be a very good first step.

We have about 2k users / day in average. So it's a small proportion but totally flooding our Sentry :(

@hofman-stripe
Copy link
Contributor

I'm curious, would you be able to figure out if for any of the impacted users, they've ever had a successful load of Stripe.js? I'm wondering if some browsers may not implement onload properly if the asset was cached.

@hofman-stripe
Copy link
Contributor

Also to avoid sentry spam, I'd recommend handling the rejection of loadStripe() and maybe disable your payment forms with a message asking the user to add an exception in their ad blocker or firewall?

@vincentaudebert
Copy link
Author

@hofman-stripe According to our Sentry it looks like it's going through the error listener and not the load one.

Capture d’écran 2020-03-25 à 10 48 25

@vincentaudebert
Copy link
Author

vincentaudebert commented Mar 25, 2020

@hofman-stripe FYI, I got rid of @stripe/stripe-js and I load js.stripe.com/v3 "manually" when needed (using inject() from stripe-js). It seems to work better now. No more errors linked to Stripe.
Well, of course, stripe-js is out so we won't have this error anymore but I mean it seems that the js file etc is loaded properly and working.

Sorry I don't have more info to help you :/

@hofman-stripe
Copy link
Contributor

it seems that the js file etc is loaded properly and working.

Are you still listening to load errors for the injected script tag?
I don't understand why there would be any difference if you still use the same logic.

@vincentaudebert
Copy link
Author

Good point, I'll add an error event listener.

Also do you think it could be possible to add an option to avoid loading js.stripe.com/v3 on every page when importing the package?
That's clearly the main reason why we had to stop using this package.

@hofman-stripe
Copy link
Contributor

hofman-stripe commented Mar 25, 2020

We inject the script on every page for fraud detection, as mentioned in the Readme here and in the documentation.

However I realize now that the unhandled rejection will be triggered even when you don't call loadStripe, which we'll look into fixing.

@vincentaudebert
Copy link
Author

On my side, I'm about to push live a better error management. I'll keep you posted if I see something odd/interesting.

Cheers.

@hofman-stripe
Copy link
Contributor

@vincentaudebert, we've released v1.3.0 which should no longer cause unhandled rejections. It won't solve the root cause of what might be causing the load errors, because those are most likely due to the user's environment.

I will close this issue, but please let us know if you discover more data on what might be causing the load errors.

@vincentaudebert
Copy link
Author

vincentaudebert commented Apr 6, 2020

@hofman-stripe looks like we could have a good guilty extension here:
https://addons.mozilla.org/fr/firefox/addon/noscript/

It matches a bit our data by the fact that it looks like we get most of the exceptions on Firefox. And there is this extension on Chrome but it's far less popular?

Nothing sure but I would probably bet on that.

PS: I'll try it when I have some spare time

@esetnik
Copy link

esetnik commented May 1, 2020

I'm seeing a large number of these errors but all on iOS / macOS safari 13.0.5

@hofman-stripe
Copy link
Contributor

@esetnik, can you clarify? Are you getting a Failed to load Stripe.js thrown by loadStripe()?

Do you have successful loads on those browsers? What percentage of failures do you see? Is there any other common properties in those failures besides the browser type? I know Safari has sometimes some strange behavior when it comes to caching, but I haven't seen those happen on the script load.

@ruuter
Copy link

ruuter commented May 26, 2020

@hofman-stripe I confirm that firefox noscript addon definitely causes the loading error. Additionally, same happens with EFF Privacy Badger.

While it's obvious those addons do that, many users today seem to install them without understanding the repercussions. I got this report from a client who had no clue those could render some sites unusable. I suspect there are many such users out there.

@mcelicalderon
Copy link

Not sure if related, but I'm using v1.5.0 and still see this error when I navigate away from the page that import { loadStripe } from '@stripe/stripe-js'; and later calls loadStripe("key"). I also tried adding the import in my app.module.ts file and had the same behavior.

Also, I'm using Angular and importing the js file in my main index file like the docs explain (without adding this it always fails). Docs say you should include like this

<script src="https://js.stripe.com/v3" async></script>

but what fixed it for me was removing async like this

<script src="https://js.stripe.com/v3"></script>

Looks like there might be a race condition somewhere but removing the async will load the library and start executing ASAP, this is also the first line in my <head> for the main index file.

I'm not a JS expert, but I'd be happy to provide more info if you think that would help, @hofman-stripe

@hofman-stripe
Copy link
Contributor

That sounds like a different issue. Seems like the module isn't able to reach the DOM to find or inject the script tag. You wouldn't be able to share a reproduction by any chance?

@mcelicalderon
Copy link

And right you are, my Content-Security-Policy was not allowing the library to load when imported. I completely removed the <script> tag and now it always works, sorry about that. Might be worth mentioning in the docs that you should allow stripe in your policy if you have one defined as the script is inserted as a side effect.

<meta http-equiv="Content-Security-Policy"
      content=" script-src 'self' https://js.stripe.com/v3">

@hofman-stripe
Copy link
Contributor

Ha yeah CSP needs to allow js.stripe.com for script-src.

Please see the Content Security Policy section of the security guide.

@vpontis
Copy link

vpontis commented Jun 17, 2020

We are seeing this issue on @stripe/stripe-js 1.5.0 and our CSP looks fine.

image

There is something going on weird in Sentry where it thinks the OS is usually Windows but that the device is usually an iPhone...

image

@jhou
Copy link

jhou commented Jul 6, 2020

We are seeing this issue on @stripe/stripe-js 1.5.0 and our CSP looks fine.

FYI, we had a similar thing and the problem was solved by editing https://js.stripe.com/v3/ in our CSP - removing the /v3/, and just having the protocol and domain there fixed it. maybe the same issue, maybe not. But might be useful for someone else in the future.

@huonghk
Copy link

huonghk commented Oct 1, 2020

@vincentaudebert I got the same issue. It's because Stripe will be loaded whenever loadStripe is imported regardless loadStripe(process.env.STRIPE_KEY) is executed or not.

import { loadStripe } from '@stripe/stripe-js';

That's why your pages still load Stripe regarless you tried to call loadStripe(process.env.STRIPE_KEY) inside useEffect.

To solve the issue, there are 2 steps

  1. Defer loading Stripe.js
    // Stripe.js will not be loaded until `loadStripe` is called import { loadStripe } from '@stripe/stripe-js/pure';

  2. Only execute loadStripe() when render needed pages

let stripePromise;
const getStripe = () => {
  if (!stripePromise) {
    stripePromise = loadStripe(process.env.REACT_APP_STRIPE_PUBLISHABLE_KEY);
  }
  return stripePromise;
};

const CheckoutPage = () => (
  <Elements stripe={getStripe()}>
    <CheckoutForm />
  </Elements>
);

Useful tutorial: https://dev.to/stripe/importing-stripe-js-as-an-es-module-1ni

@hofman-stripe
Copy link
Contributor

@huonghk I don't see why defer loading the script would allow it to successfully load, but loading it early would fail.

Defer loading Stripe.js has negative implications for fraud detection and is not recommended.

@archywillhe
Copy link

archywillhe commented Nov 21, 2020

just realised the error is try..catch-able at the await portion of the code even if we are globally loading it (instead of defering loading) and this is very good to know!

so in cosole you can see the network error (and in code it's still catchable when you await that promise!)

@langer
Copy link

langer commented Mar 5, 2021

For anyone who may still be coming across this error, we were mystified by this ourselves, and witnessing it only affecting Safari and Mobile Safari users. It turns out the errors were not adversely affecting our users at all — what was happening was, we use auth0 for our identity provider, and lean on the loginWithRedirect() method from their useAuth0 React hook, and what was happening was a user was being redirected before the stripe.js asset had completed loading, which was triggering the event listener here to fire. I can easily reproduce this by selecting "Clear History..." in Safari and visiting our site, and each time I do it the error is fired.

cc @hofman-stripe, this may be of interest to you.

@Stavtastic
Copy link

I am running into this issue on localhost and heroku with firefox 86.0. Chrome, Edge are working fine. This is not negatively impacting the redirect to the check-out page. It is just a console error that is annoying.

@RoniqueRicketts
Copy link

This error is raised if the script failed to load (e.g. network error), or loaded but didn't execute properly (didn't register Stripe on the global).

Do you have any CSP that might interfere with loading of the Stripe.js script? Maybe those customers have extensions installed blocking some 3rd party scripts? Do you have metrics on how often this happens? Are most Firefox users able to load without errors?

Unless you can gather more details from an impacted user, I'm not sure we'd be able to track down the cause.

And how do we fix this particular issue?

@bozzmedia
Copy link

bozzmedia commented Feb 22, 2023

Running into this issue recently, so far only in Chrome on Win10.

@yashraut19
Copy link

Same i am facing this issue on chrome and win10.

@mifi
Copy link

mifi commented Mar 21, 2023

I found a way to reproduce this problem in dev:

First, make sure you load Stripe using the pure variant, and then have a retry wrapper that will call loadStripe again if it fails:

import { loadStripe } from '@stripe/stripe-js/pure';

const stripePromise = (async () => {
  for (;;) {
    try {
      // This sleep here makes it easier to reproduce locally, we're delaying the loading of Stripe
      await new Promise((r) => setTimeout(r, 20000));

      return await loadStripe('API_KEY');
    } catch (err) {
      console.error(err);
      await new Promise((r) => setTimeout(r, 5000));
    }
  }
})();

Now to reproduce:

  1. Load your webapp in your browser in dev
  2. Within 20 sec, go to devtools and under network throttling, set it to "Offline"
  3. Wait and observe that it logs Error: Failed to load Stripe.js
  4. Now go back into devtools, and turn off throttling
  5. Wait and see that it tries to call loadStripe again, but it keeps on failing with the same error every 5 seconds

This means retry doesn't work and once you have received the error Error: Failed to load Stripe.js, the only thing that helps is to reload the whole page:

const stripePromise = (async () => {
  try {
    return await loadStripe('API_KEY');
  } catch (err) {
    console.error(err);
    window.location.reload();
  }
})();

I see this happening a lot in the wild in production environments, so it's not just in dev.

I definitely think this is a bug in Stripe.js and should be fixed, as I think it will lead to horrible UX, as it will make the Stripe Elements hang forever when the customer wants to pay...

@cyzanfar
Copy link

Why is this issue closed when there are many people experiencing the same problem? @hofman-stripe

@moshfiqrony
Copy link

How about this one

function getStripePromise () {
    const { loadStripe } = require("@stripe/stripe-js")
    return loadStripe('your_key_here')
}

It doesn't load the iframe always. It will only load when the loadStripe promise will be initiated.

@Cloud11PL
Copy link

I can't believe there's still no fix for this, it's the most common error we have in Sentry. Reloading entire page sounds like a UX nightmare 😬

@mifi
Copy link

mifi commented Oct 10, 2023

I think someone just needs to open a new issue. Maybe the Stripe team doesn't read closed issues

@ollebergkvist
Copy link

Also seeing this...

@brendanm-stripe
Copy link
Contributor

Hey folks, I/we have been keeping an eye on this as more examples roll in. While this is currently expected behaviour (not a bug), it's also not ideal. @mifi 's clear repro/example earlier this year prompted me to press the team to see about improving this.

As you can see in the above-linked PR, we're working on revising this to allow for programmatic retries without getting the cached failure.

@enkay
Copy link

enkay commented Dec 23, 2023

Getting lots of these too.

@esetnik
Copy link

esetnik commented Feb 27, 2024

Still seeing this error as well

@brendanm-stripe
Copy link
Contributor

@esetnik If you're seeing a consistent errors related to loading Stripe.js with this package, please open a new issue and share details such as:

  • Exact code & error message(s)
  • Package version you're using
  • Ideally a minimal reproduction or live example we can inspect

@mswezey23
Copy link

Still experiencing this with this tech stack:

React v18
RTK
Chakra UI
hosted via AWS Amplify
Auth0 was our auth provider
Sentry as our monitoring provider

Over 130 events of this in the last 30 days. Luckily our dashboard isn't used to heavily, but it's still annoying for our oncall rotation. Luckily I found this thread, so I'll link it to our Jira ticket(s) so we can monitor the situation.

@bennybrau
Copy link

Just thought I would drop this in here.

We have been dealing with blasts of this error in our Sentry logs a couple times a week for the last month or so. After looking at Cloudflare logs, we are pretty sure its actually coming from Microsoft's cloud...probably Outlook.com prefetching images from our site for emails (we do email marketing for experiences and our site is a marketplace with images for each event). So, basically Azurebots are loading pages but Stripe.js fails to load in their environment. This sucks because its a ton of noise that masks legitimate Stripe loading errors...but just thought I would drop this in there in case others are dealing with the same thing.

@fruchtose-stripe
Copy link
Contributor

Hi @mswezey23 @bennybrau. If Stripe.js fails to load, the error message is expected. Managing error messages is an integration question, and we aren’t able to answer those here on GitHub. Please reach out to Stripe Support for help with integration issues.

@thatsanicehat
Copy link

Since Stripe isn't interested in implementing this feature or documenting ways to manage it, and it's clearly a common enough problem that this issue continues to get traffic, someone else wrote a solution that may work for you: https://github.com/wobsoriano/retry-stripe-loader

@mifi
Copy link

mifi commented Jul 3, 2024

Since Stripe isn't interested in implementing this feature or documenting ways to manage it, and it's clearly a common enough problem that this issue continues to get traffic, someone else wrote a solution that may work for you: https://github.com/wobsoriano/retry-stripe-loader

a fix was already implemented in #518 - afaik you can now call loadStripe again if it rejects and it should try again

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet