react-native: Excessive number of pending callbacks: 501

React Native version:

System: OS: macOS Mojave 10.14.6 CPU: (4) x64 Intel® Core™ i5-3210M CPU @ 2.50GHz Memory: 22.95 MB / 8.00 GB Shell: 3.2.57 - /bin/bash Binaries: Node: 10.15.1 - /usr/local/bin/node npm: 6.4.1 - /usr/local/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman SDKs: iOS SDK: Platforms: iOS 12.2, macOS 10.14, tvOS 12.2, watchOS 5.2 Android SDK: API Levels: 22, 23, 24, 25, 26, 27, 28, 29 Build Tools: 27.0.3, 28.0.2, 28.0.3, 29.0.1, 29.0.2 System Images: android-23 | Google APIs Intel x86 Atom, android-28 | Google APIs Intel x86 Atom, android-28 | Google APIs Intel x86 Atom_64, android-28 | Google Play Intel x86 Atom, android-28 | Google Play Intel x86 Atom_64 IDEs: Android Studio: 3.4 AI-183.6156.11.34.5692245 Xcode: 10.2.1/10E1001 - /usr/bin/xcodebuild npmPackages: react: 16.9.0 => 16.9.0 react-native: 0.61.5 => 0.61.5 npmGlobalPackages: react-native-cli: 2.0.1 react-native-git-upgrade: 0.2.7 Screen Shot 2019-12-11 at 16 55 33

Steps To Reproduce

Describe what you expected to happen:

Snack, code example, screenshot, or link to a repository:

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 47
  • Comments: 88 (2 by maintainers)

Commits related to this issue

Most upvoted comments

I’m getting this from using a TouchableOpacity inside of a Flatlist or a Scrollview. Very odd and I do not know why, but when I replace it with the TouchableOpacity from the react-native-gesture-handler package it works fine.

I had this error because I was looping and queuing hundreds of promises like

await Promise.all(filesToDownload.map(url => fetch(url)))

not the best plan… from the code it looks this warning is fired when there are more than 500 things pending in the message queue that hands runtime async calls off to the native code. (I’m new to this code so just a quick interpretation) https://github.com/facebook/react-native/blob/ce1703a84d2712a7df8f93a3f3ecbb2c04b72e57/Libraries/BatchedBridge/MessageQueue.js#L210

I ended up switching to Bluebird’s Promise.map() function that has a concurrency option to limit how many promises are called at a time http://bluebirdjs.com/docs/api/promise.map.html#map-option-concurrency or you could use Async’s mapLimit() https://caolan.github.io/async/v3/docs.html#mapLimit

maybe firebase caused the problem ?

This issue is occuring because you are using useEffect in many functions to check for every change in state. Reduce this number and see the magic happening.

Wrong Approach: useEffect(() => { } ); Correct Approach: useEffect(() => { }, [ ] );

Replace this wherever possible.

I solved this issue within 24 hours of facing.

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community’s attention? This issue may be closed if no further activity occurs. You may also label this issue as a “Discussion” or add it to the “Backlog” and I will leave it open. Thank you for your contributions.

I have the same issue

“react-native”: “https://github.com/expo/react-native/archive/sdk-44.0.0.tar.gz”,

Please report: Excessive number of pending callbacks: 501. Some pending callbacks that might have leaked by never being called from native code: {“15059”:{},“15060”:{},“15061”:{},“15062”:{},“15063”:{},“15064”:{},“15065”:{},“15066”:{},“15067”:{},“15068”:{},“15069”:{},“15070”:{},“15071”:{},“15072”:{},“15073”:{“module”:“UIManager”,“method”:“measure”},“15074”:{},“15075”:{},“15076”:{},“15077”:{},“15078”:{},“15079”:{},“15080”:{},“15081”:{},“15082”:{},“15083”:{},“15084”:{},“15085”:{},“15086”:{},“15087”:{},“15088”:{},“15089”:{},“15090”:{},“15091”:{},“15092”:{},“15093”:{},“15094”:{},“15095”:{},“15096”:{},“15097”:{},“15098”:{},“15099”:{},“15100”:{},“15101”:{},“15102”:{},“15103”:{},“15104”:{},“15106”:{},“15107”:{},“15108”:{},“15109”:{},“…(truncated keys)…”:451}

This is happening to me with RN 0.63.2. I was on 0.61.5 and updated packages just 2 weeks before and this is a big issue for us since we are in production.

Edit - I had updated all the packages including navigation. the app just hangs while navigating between the screen via bottom tab bar. everything was working fine in 0.61.5 and react-navigation 4.x

I’m also getting this when I have over 78 TouchableOpacity in a ScrollView. When I only have 77 it works fine. There is also a relationship to having a setState call within a .then() elsewhere in my component - this is actually where the warning seems to originate according to the warning’s call stack. I can avoid the warning by doing any one of these three things: 1) change TouchableOpacity to Pressable, 2) keep the number of TouchableOpacity in the ScrollView to under 78, or 3) remove the setState() call from .then() on one of my async actions. I don’t understand it, but am able to at least move on now.

“react”: “18.0.0”, “react-native”: “0.69.6”

After I saw many codes with that error I figure out that the common piece of code is setState inside .then() method which cause an Excessive callbacks similar to an infinite loop so as solution you can remove that setState and if it necessary use Ref instead to avoid re-render

It seems that it is indeed the TouchableOpacity - caused by a typo introduced here: https://github.com/facebook/react-native/commit/3eddc9abb70eb54209c68aab7dbd69e363cc7b29

There’s a PR for a fix here: https://github.com/facebook/react-native/pull/35387

In the meanwhile, you should be able to patch TouchableOpacity.js according to the above PR if you are not in a poisiton to migrate to the TouchableOpacity provided by RNGH

I lost hope in Javascript. 😢

I have this simple function:

private getAttachmentTypeNames(): string[]{
    const { attachment_categories } = this.state;
    if (nullish(attachment_categories?.types)) {
	    return [];
    }
    const photo_type:string[] = [];
    for (let i = 0; i < attachment_categories?.types.length; i++){
	    photo_type.push(attachment_categories?.types[i]);
    }
    return photo_type;
}

Which gives me this Excessive number of pending callbacks: 501 error.

By changing the function to following, solved the issue: (WHY!!!)

private async getAttachmentTypeNames():Promise<string[]>{
        const { attachment_categories } = this.state;
        if (nullish(attachment_categories?.types)) {
	        return [];
        }
        const types = get.cloned<string[]>(attachment_categories?.types); // nothing special here
        const photo_type:string[] = [];
        for await (const type of types) {
	        photo_type.push(type);
        }
        return photo_type;
}

@safaiyeh I think a better warning that points to the culprit would be useful. My project uses react-native 0.63.3 and react-native-maps 0.27.1 and I didn’t find out yet where the problem is starting.

What I see common in all the comments is the fact that the developer doesn’t know why this error is thrown.

Also, @MrShakes - no need to reinvent the wheel. https://www.npmjs.com/package/patch-package is perfect for this use-case

same problem. module: ReanimatedModule, method: getValue; module: RNC_AsyncSQLiteDBStorage, method: multiGet

@gabrielmoncea Yeah, it would definitely help, if the error message would include at least the callback function that is still pending for execution.

Hi all! Since activity popped up here again, could someone reproduce this on a fresh RN template? There are some hints that react-navigation is the root cause?

i use react navigation, but for me, i dont found any problem with that.

my screen had countdown, after i tried disable the countdown, the warning is gone. So i found the source of my problem

my countdown is set in state for remaining minute & remaining second. so every second we update it by setState.

_runCountdown = () => {
    this.myinterval = setInterval(() => {
      if (this.state.remainingSecond > 0) {
        this.setState({ remainingSecond: (this.state.remainingSecond - 1) });
      } else if (this.state.remainingMinute === 0) {
        clearInterval(this.myinterval); // STOP COUNTDOWN
        this._cancelOrder('ALL', 'ALERT', 'Pesanan Anda dibatalkan karena melewati batas waktu pemesanan'); // RUN CANCEL ORDER
      } else {
        this.setState({ remainingSecond: 59 });
        this.setState({ remainingMinute: (this.state.remainingMinute - 1) });
      }
    }, 1000);
  }

This happens to me with RN 0.62.2, and didn’t happen to me on earlier versions of RN (I upgraded from 0.59.9).

Is this going to be fixed?

I’m also getting this when I have over 78 TouchableOpacity in a ScrollView. When I only have 77 it works fine. There is also a relationship to having a setState call within a .then() elsewhere in my component - this is actually where the warning seems to originate according to the warning’s call stack. I can avoid the warning by doing any one of these three things: 1) change TouchableOpacity to Pressable, 2) keep the number of TouchableOpacity in the ScrollView to under 78, or 3) remove the setState() call from .then() on one of my async actions. I don’t understand it, but am able to at least move on now.

“react”: “18.0.0”, “react-native”: “0.69.6”

Using Pressable worked for me.

Hi. Also encountered this problem.

“react”: “18.0.0”, “react-native”: “0.69.5”, “@react-navigation/bottom-tabs”: “^6.3.2”, “@react-navigation/native”: “^6.0.11”,

This was a really hard one for me to track down.

What it came down to: This would only occur when I was running on a low spec device (Galaxy A12). I had a hook that looked like this:

  const [state, setState] = useState(1);
  useEffect(() => {
    const t = setInterval(
      () => setState(valueGoesHere),
      200,
    );
    return () => clearInterval(t);
  }, []);

To poll a value.

This worked fine on higher spec’d phones but it caused the excessive promise issue. You should comb your code for anything like the above snippet.

I updated my React Native version from 0.63.2 to 0.63.3, with initial testing I’m not getting this error, I will update if I’m getting this error with 0.63.3

Update I’m still getting the error, but not as frequent as It was before and the app is usable.

Unfortunately, we have the same issue, but in our case its the @react-native-community/async-storage causing the excessive number of pending callback. But there is one very interesting thing: the issue doesn’t come just from nowhere, it only happens, if we change the GoogleService-Info.plist to a different Firebase project or app bundle id.

Some more detailed repro:

  1. We had used a certain firebase config in GoogleService-Info.plist for a long time, e.g. for the bundleID com.mycompany.ourfancyapp and the firebase project id our-fancy-app-dev.
  2. Then, as we need to distribute the app to our client’s private app store, we need to change the config to bundleID com.client.myapp and to a new Firebase project created to store specifically the client’s data, e.g. projectID our-fancy-app-for-client-x.
  3. As needed, we have registered a new bundleID within the new Firebase project and downloaded a new GoogleService-Info.plist file. But when we replaced the old firebase config file with the new one and ran the app, we could login using the new client-facing database, but after the login the whole app works, but it is extremely slow and nearly not usable (you have to click on an item 10 times and then wait for 2-3 minutes until it opens (sometimes it doesn’t react at all)). In addition to that, the same error as described in this issue is shown, but for our case its showing a lot of RNCAsyncStorage pending callbacks:
Bildschirmfoto 2020-09-27 um 23 09 59
  1. The funny thing is, if we close the hanging app, move back the old GoogleService-Info.plist for the old dev bundleID and projectID, then the app is not lagging anymore and the error regarding pending callbacks doesn’t appear at all! 🤯

We use the latest module versions, here some detailed info: react-native: 0.63.2 react: 16.13.1 @react-native-firebase/app: 8.4.4 @react-native-firebase/auth: 8.0.10 @react-native-firebase/firestore: 7.8.4 @react-native-firebase/messaging: 7.8.9 @react-native-community/async-storage: 1.12.0

Our team would really appreaciate, if some of you guys can find a solution for this issue soon. Because, otherwise we are going to lose our client as we can’t deliver the app in time 😢 Thank you very much in advance! 👍

Still experiencing this on v63.2 (react-navigation v5). Any updates?

I had this also - thanks a lot! It was also the TouchableOpacity for me - I had this issue when using FlatList with pagination so list would grow to be quite large.

I switched to using TouchableRipple from react native paper which solved the issue.

If you have a list/iterable of functions that return Promises, you can await for each promise/iteration.

Example:

const listOfPromises = [() => Promise<any>, () => Promise<any> .... ]

const awaitPromises = async () => {
        for await (const promise of listOfPromises) {
              const res = await promise()
              .... more code
        }
}

That way you won’t stack up promise-tasks, you’ll deal with them one at a time. This is just an alternative to the promise-task parallelization options mentioned here in the thread.

You can also try to make your list of Promises a list of functions that return Promises, and then use my suggestion.

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community’s attention? This issue may be closed if no further activity occurs. You may also label this issue as a “Discussion” or add it to the “Backlog” and I will leave it open. Thank you for your contributions.

@SplinterStan thank you for the response. For me it also was the error in my code… Redundant dep in useEffect, which caused cycle with AsyncStorage.setItem calls

Problem Statement:
Experiencing an excessive number of pending callbacks: 501.

React Native Version:
0.73.4

Debug Steps:
I began removing each component from top to bottom, starting with drilling down from App.tsx, until I narrowed down the problem to specific components.

Possible Solution:
In my case, the issue was with the Icon components wrapped in the Box component. By commenting or making it conditional rendering on this section, the warning disappeared.

(<Box>{*<Icon/>*}<Texr>Fixed</Text></Box>)

Hello everyone,

This is my first contribution, and I hope it’s helpful even though the issue is already closed.

I unexpectedly encountered the multiple callback error. Everything was fine, but one morning, I started my project and was greeted with this error. While the TouchableOpacity from React-Native-Gesture-Handler resolved most of the issues, there were instances where the error persisted. What worked consistently for me is the Pressable component from React Native. It may sound too straightforward, but after thorough testing, I can confidently say that this resolved my issue.

Hopefully, this can assist someone else as well.

If you have a list/iterable of functions that return Promises, you can await for each promise/iteration.

Example:

const listOfPromises = [() => Promise<any>, () => Promise<any> .... ]

const awaitPromises = async () => {
        for await (const promise of listOfPromises) {
              const res = await promise()
              .... more code
        }
}

That way you won’t stack up promise-tasks, you’ll deal with them one at a time. This is just an alternative to the promise-task parallelization options mentioned here in the thread.

You can also try to make your list of Promises a list of functions that return Promises, and then use my suggestion.

Awaiting solved the same problem.

I am rendering images in a list (Flatlist) and in the renderItem component, I am trying to get the actual size of the image using Image.getSize(), though it works fine but gives the same warning.

I’m getting this from using a TouchableOpacity inside of a Flatlist or a Scrollview. Very odd and I do not know why, but when I replace it with the TouchableOpacity from the react-native-gesture-handler package it works fine.

I can also confirm that this did the trick for me 🥳

I’m getting this from using a TouchableOpacity inside of a Flatlist or a Scrollview. Very odd and I do not know why, but when I replace it with the TouchableOpacity from the react-native-gesture-handler package it works fine.

WTF, I confirm this did the trick for me! Thanks a million!!! NOTE TO OTHERS: make sure to change the import statement also on your components.

++ on RN 0.65.0

maybe firebase caused the problem ?

in my case, wrong firebase collection subscription caused too many network connections

In my case, I was using expo-location and expo-task-manager to fetch locations in background, everything was working fine but somehow these errors starting showing up. After investigating for a while, I saw that useEffect was missing dependency list. Which triggered the listener again and again and again. Therefore, after adding the list, the problem was solved. A small mistake.

Good tip, definitely would have taken me some time to get that. Many thanks again.

This happens to me with RN 0.62.2, and didn’t happen to me on earlier versions of RN (I upgraded from 0.59.9). Is this going to be fixed?

same with me. mine was 0.59.8 and upgrade to 0.61.5 so this is still no solution?

RN upgrade 16.13.1 the problem still exist

@hotaryuzaki Take a deeper look in your code. There is definitely something that is causing an infinite callback loop as it was in our case with Firebase subscriptions.

For me there is nothing to do with firebase, and I think the main problem not the firebase. In my case the problem is because countdown/timer using setInterval. When I disable the interval function the issue is gone.

@Badbreaddead Yes, after 2 weeks of painful search we’ve found the issue! It was indeed in our application code! We are using Firebase Snapshots to subscribe to live changes in firesore collections. We have 2 of the subscriptions in 1 component running in series (if Subscription 1 emits a value, then we are unsubscribing from the 2nd subscription and resubscribe to it again), e.g.:


...
  let unsubscribeFromGroupDocument = () => { };
  let unsubscribeNewslettersCollection = () => { };

  useEffect(() => {
    // Subscribe to Group document changes.
    unsubscribeFromGroupDocument = subscribeCurrentGroup();
    return () => {
      unsubscribeFromGroupDocument();
      unsubscribeNewslettersCollection();
    };
  }, []);

  /**
   * Subscribes to the current group referenced in the user document.  
   */
  function subscribeCurrentGroup() {
    return firestore()
      .collection('groups')
      .doc(userDocument.groupId)
      .onSnapshot((groupDocument) => {
        if (loggedUser() && groupDocument.data()) {
          const groupDoc = groupDocument.data();
          setGroupDocument(groupDoc);
          persistDataInDevice('group', groupDoc);
          unsubscribeNewslettersCollection = subscribeToNewsletters(groupDoc);
        }
      }, () => {
        getPersistedDataFromDeviceMemory('group', true)
          .then((groupDoc) => {
            if (groupDoc) {
              setGroupDocument(groupDoc);
            }
          })
          .catch((error) => console.log('Error while getting group document data: ', error));
      });
  }

  /**
   * Subscribes to all newsletters in the newsletter collection.
   * @param {GroupDocument} groupDoc Firebase group document object of the user group.
   */
  function subscribeToNewsletters(groupDoc) {
    return firestore()
      .collection('newsletters')
      .onSnapshot((newslettersCollectionDocument) => {
        if (loggedUser() && newslettersCollectionDocument.docs.length > 0) {
          const newslettersCollection = newslettersCollectionDocument.docs.map(element => element.data());
          let allowedNewslettersLocal = newslettersCollection.filter((newsletterDoc) => groupDoc.newsletters.includes(newsletterDoc.id));
          persistDataInDevice('newsletters', allowedNewsletters);
          setAllowedNewsletters(allowedNewslettersLocal);
        }
      }, () => {
        getPersistedDataFromDeviceMemory('newsletters', true)
          .then((allowedNewsletters) => {
            if (allowedNewsletters) {
              setAllowedNewsletters(allowedNewsletters);
            }
          })
          .catch((error) => console.log('Error while getting newsletters collection data: ', error));
      });
  }

  /**
   * When a user group changes in the user document,
   * unsubscribes from active user group and newsletter collection subscriptions and subscribes anew.
   */
  function resubscribeToGroup() {
    unsubscribeFromGroupDocument();
    unsubscribeNewslettersCollection();
    unsubscribeFromGroupDocument = subscribeCurrentGroup();
  }

  return (
    <GroupDocumentProvider value={[groupDocument]}>
      <NewslettersProvider value={[allowedNewsletters]}>
        {
          userDocument && groupDocument && userDocument.groupId !== groupDocument.groupId && resubscribeToGroup()
        }
        <Stack.Navigator...

So, I don’t exactly know which line of code caused the freeze/hanging issue, but I suppose that it was the infinite amount of resubscriptions done in the line userDocument && groupDocument && userDocument.groupId !== groupDocument.groupId && resubscribeToGroup(). As we are trying to cache the data from Firebase in the device memory using AsyncStorage, maybe there were asynchronity-related issues.

EDIT: I just tested the old code and this exactly function call resubscribeToGroup() is causing the issue! If I remove it, the app works flawlessly!

@SplinterStan have you found a way to solve the problem? We have exactly the same problem

Hi @SplinterStan i would recommend opening an issue with react native firebase.

Hi all! Since activity popped up here again, could someone reproduce this on a fresh RN template? There are some hints that react-navigation is the root cause?

I had this error because I was looping and queuing hundreds of promises like

await Promise.all(filesToDownload.map(url => fetch(url)))

not the best plan… from the code it looks this warning is fired when there are more than 500 things pending in the message queue that hands runtime async calls off to the native code. (I’m new to this code so just a quick interpretation)

https://github.com/facebook/react-native/blob/ce1703a84d2712a7df8f93a3f3ecbb2c04b72e57/Libraries/BatchedBridge/MessageQueue.js#L210

I ended up switching to Bluebird’s Promise.map() function that has a concurrency option to limit how many promises are called at a time http://bluebirdjs.com/docs/api/promise.map.html#map-option-concurrency or you could use Async’s mapLimit() https://caolan.github.io/async/v3/docs.html#mapLimit

i dont think i have this in my code. but my screen had countdown. and after i tried disable the countdown, the warning is gone. So i found the source of this problem

my countdown is set in state for remaining minute & remaining second. so every second we update it by setState. i think it is a bug in RN.