Skip to content

TypeError: Network request failed randomly in IOS #49037

Description

@Nader-CS

Description

some users reported network request failed using rtk query or TypeError: Network request failed randomly for some api's and others works fine , according to this issue opened by me in redux toolkit link , the issue arises from react native environment , this issue happen randomly in ios , i mean same user in other device can request this api and works fine , the request not even reaches to our server.

api.config

import {createApi, fetchBaseQuery} from '@reduxjs/toolkit/query/react';
import Config from 'react-native-config';
import {I18nManager, Platform} from 'react-native';
import {getToken, getGuestPublicToken} from '@selectors';
import qs from 'qs';
import {getAppVersion} from '@utils/helpers';

const baseQuery = fetchBaseQuery({
  baseUrl: `${Config.API_URL}`,
  paramsSerializer: params => qs.stringify(params, {arrayFormat: 'brackets'}),
});

const baseQueryWithInterceptor = async (args, api, extraOptions) => {
  const version = (await getAppVersion()).substring(1).split(' ')[0];
  const state = api.getState();
  const privateToken = getToken(state);
  const publicToken = getGuestPublicToken(state);

  args.headers = {
    ...args.headers,
    'Accept-Language': I18nManager.isRTL ? 'ar' : 'en',
    'User-Agent': Platform.OS,
    'App-Version': version,
    Authorization: `Bearer ${
      privateToken ? privateToken?.access_token : publicToken?.access_token
    }`,
  };
  let result = await baseQuery(args, api, extraOptions);

  if (__DEV__) {
    console.log(api.endpoint, args, result);
  }

  return {
    ...result,
    error: result?.error?.data || result?.error,
  };
};

export const api = createApi({
  baseQuery: baseQueryWithInterceptor,
  endpoints: () => ({}),
  invalidationBehavior: 'immediately',
  tagTypes: [
    'Customer',
    'order',
    'Cards',
    'ActiveCoupons',
    'ExpiredCoupons',
    'Wallet',
    'WalletHistory',
    'PromoCode',
    'GetRunningOrder',
    'Banners',
    'ContactMessages',
  ],
});

profile.js

import {Animated, StyleSheet, View, Image, RefreshControl} from 'react-native';
import React, {memo, useCallback, useMemo, useRef, useState} from 'react';
import {useTranslation} from 'react-i18next';
import {useNavigation} from '@react-navigation/native';
import {useSelector} from 'react-redux';
import {getToken} from '@selectors';
import {
  useGetCustomerQuery,
  useGetQuestionnaireQuery,
  useGetWalletQuery,
} from '@services';
import {
  ProfileButton,
  ProfileInfo,
  QuestionnaireCard,
  ReferCard,
  Button,
  EmptyView,
  ErrorView,
  LoadingView,
  Header,
  CheckMobileVerified,
} from '@components';
import {
  crypto,
  profile_heart,
  wallet2,
  edit,
  profile2,
  region,
  coupon,
  credit2,
  tims_bag,
} from '@assets';
import {moderateScale, moderateVerticalScale} from 'react-native-size-matters';
import {colors, typo} from '@common';
import {TouchableOpacity} from 'react-native-gesture-handler';
import Modal from 'react-native-modal';
import {convertEnglishNumbersToArabic} from '@utils';
import {commonStyles} from '@utils/constants';

const EditProfileButton = memo(() => {
  const {navigate} = useNavigation();
  return (
    <TouchableOpacity
      onPress={() => navigate('EditProfile')}
      style={styles.item}>
      <Image style={styles.editIcon} source={edit} />
    </TouchableOpacity>
  );
});
const EditCountryButton = memo(() => {
  const {navigate} = useNavigation();
  return (
    <TouchableOpacity onPress={() => navigate('Country')} style={styles.item}>
      <Image style={styles.editIcon} source={region} tintColor={colors.white} />
    </TouchableOpacity>
  );
});

const Profile = () => {
  const {t} = useTranslation();
  const navigation = useNavigation();
  const isLoggedIn = useSelector(getToken);
  const [isModalVisible, setModalVisible] = useState(false);

  const {
    data,
    isLoading: isLoadingQuestionnaire,
    isError: isLoadingQuestionnaireError,
    refetch: refetchQuestionnaire,
    error: gettingQuestionnaireError,
  } = useGetQuestionnaireQuery(undefined, {skip: !isLoggedIn});

  const toggleModal = () => {
    setModalVisible(!isModalVisible);
  };
  const {
    currentData: user = {},
    refetch: refetchCustomer,
    isLoading: isGettingCustomer,
    isFetching: isFetchingCustomer,
    isError: isGettingCustomerError,
    error: gettingCustomerError,
  } = useGetCustomerQuery(undefined, {
    skip: !isLoggedIn,
  });
  const {
    data: {user_wallet} = {},
    isLoading: isFetchingWallet,
    isError: isFetchingWalletError,
    refetch: refetchWallet,
    error: gettingWalletError,
  } = useGetWalletQuery(undefined, {
    skip: !isLoggedIn,
  });
  const isLoading = useMemo(
    () =>
      [isLoadingQuestionnaire, isGettingCustomer, isFetchingWallet].some(
        Boolean,
      ),
    [isLoadingQuestionnaire, isGettingCustomer, isFetchingWallet],
  );
  const hasError = useMemo(
    () =>
      [
        isLoadingQuestionnaireError,
        isGettingCustomerError,
        isFetchingWalletError,
      ].some(Boolean),
    [
      isLoadingQuestionnaireError,
      isGettingCustomerError,
      isFetchingWalletError,
    ],
  );

  const error = useMemo(
    () =>
      [
        gettingQuestionnaireError,
        gettingCustomerError,
        gettingWalletError,
      ].find(Boolean),
    [gettingQuestionnaireError, gettingCustomerError, gettingWalletError],
  );

  const scrollY = useRef(new Animated.Value(0)).current;
  const isScrolling = useRef(false);

  const handleScrollBeginDrag = () => {
    isScrolling.current = true;
  };
  const navigationFromProfile = useCallback(
    screenName => {
      navigation.navigate(screenName);
    },
    [navigation],
  );

  const emptyViewActions = useMemo(
    () => [
      {
        title: t('sign_in').toUpperCase(),
        type: Button.types.PRIMARY,
        onPress: () =>
          navigation.navigate('AuthStack', {
            screen: 'Login',
          }),
      },
    ],
    [navigation],
  );

  const image = useMemo(
    () => (user?.avatar ? {uri: user?.avatar} : profile2),
    [user],
  );
  const onRetry = useCallback(
    () =>
      Promise.all([
        isGettingCustomerError && refetchCustomer(),
        isLoadingQuestionnaireError && refetchQuestionnaire(),
        isFetchingWalletError && refetchWallet(),
      ]),
    [
      isGettingCustomerError,
      isLoadingQuestionnaireError,
      refetchCustomer,
      refetchCustomer,
      isFetchingWalletError,
      refetchWallet,
    ],
  );
  const walletInfo = useMemo(
    () =>
      `${t('balance')} : ${convertEnglishNumbersToArabic(
        Number(user_wallet?.total || 0).toFixed(2),
      )} ${user_wallet?.currency}`,
    [user_wallet, convertEnglishNumbersToArabic],
  );
  const opacity = scrollY.interpolate({
    inputRange: [0, 50],
    outputRange: [1, 0],
    extrapolate: 'clamp',
  });
  const scale = scrollY.interpolate({
    inputRange: [0, 50],
    outputRange: [1, 0.8],
    extrapolate: 'clamp',
  });
  const onRefresh = () => {
    refetchCustomer();
  };
  return (
    <>
      <View>
        <Header
          rightItem={isLoggedIn ? EditProfileButton : EditCountryButton}
          title={isLoggedIn ? null : t('profile')}
        />
      </View>
      {isLoggedIn ? (
        <LoadingView isLoading={isLoading} containerStyle={styles.loadingView}>
          <ErrorView hasError={hasError} onRetry={onRetry} error={error}>
            <Animated.View
              style={[
                styles.profileImgContainer,
                {opacity, transform: [{scale}]},
              ]}>
              <View>
                <TouchableOpacity
                  onPress={toggleModal}
                  style={styles.imageContainer}>
                  <View style={styles.profileImage}>
                    <Image source={image} style={styles.image} />
                  </View>
                </TouchableOpacity>
              </View>
            </Animated.View>
            <View style={[styles.mainContainer(user?.verified)]}>
              <Animated.ScrollView
                keyboardShouldPersistTaps="always"
                refreshControl={
                  <RefreshControl refreshing={false} onRefresh={onRefresh} />
                }
                onScroll={Animated.event(
                  [{nativeEvent: {contentOffset: {y: scrollY}}}],
                  {useNativeDriver: true},
                )}
                onScrollBeginDrag={handleScrollBeginDrag}
                scrollEventThrottle={16}
                bounces={false}
                showsVerticalScrollIndicator={false}>
                <View style={styles.container}>
                  <ProfileInfo />
                  <QuestionnaireCard />
                  <View style={styles.separator} />
                  <ReferCard />
                  <ProfileButton
                    icon={tims_bag}
                    label={t('my_orders')}
                    showBorderBottom={true}
                    onPress={() => navigationFromProfile('MyOrders')}
                  />
                  <ProfileButton
                    icon={crypto}
                    label={t('points_analysis')}
                    showBorderBottom={true}
                    onPress={() => navigationFromProfile('PointsAnalysis')}
                  />
                  <ProfileButton
                    icon={profile_heart}
                    label={t('favorites')}
                    showBorderBottom={true}
                    onPress={() => navigationFromProfile('Favorites')}
                  />
                  <ProfileButton
                    icon={credit2}
                    label={t('my_cards')}
                    showBorderBottom={true}
                    onPress={() => navigationFromProfile('MyCards')}
                  />
                  <ProfileButton
                    icon={wallet2}
                    label={t('wallet')}
                    label2={walletInfo}
                    showBorderBottom={true}
                    onPress={() => navigationFromProfile('Wallet')}
                  />
                  <ProfileButton
                    icon={coupon}
                    label={t('Coupons')}
                    showBorderBottom={true}
                    onPress={() => navigationFromProfile('Coupons')}
                  />
                  {/* <ProfileButton
                    icon={location}
                    label={t('my_addresses')}
                    showBorderBottom={true}
                    onPress={() => navigationFromProfile('MyAddresses')}
                  /> */}
                  <ProfileButton
                    icon={region}
                    label={t('country')}
                    icon2={user?.client_country?.country?.image_url}
                    onPress={() => navigationFromProfile('Country')}
                  />
                </View>
              </Animated.ScrollView>
              {!user?.verified && (
                <CheckMobileVerified isMobileVerified={user?.verified} />
              )}
              <Modal isVisible={isModalVisible} onBackdropPress={toggleModal}>
                <View style={styles.overlay}>
                  <View style={styles.modalContainer}>
                    <Image source={image} width="100%" height="100%" />
                  </View>
                </View>
              </Modal>
            </View>
          </ErrorView>
        </LoadingView>
      ) : (
        <View style={styles.fullHeight}>
          <EmptyView
            iconName={'account-alert-outline'}
            iconColor={colors.gray}
            title={t(
              'sign_in_or_register_to_unlock_your_rewards_and_earn_points',
            )}
            actions={emptyViewActions}
            titleStyle={styles.emptyViewTitle}
            iconNameSize={moderateScale(100)}
            actionsContainer={styles.actionsContainer}
          />
        </View>
      )}
    </>
  );
};

export default memo(Profile);

const styles = StyleSheet.create({
  mainContainer: isVerified => ({
    flex: 1,
    backgroundColor: colors.white,
    width: '100%',
    paddingBottom: isVerified ? 0 : moderateVerticalScale(50),
  }),
  loadingView: {
    flex: 1,
  },
  separator: {
    height: moderateVerticalScale(11),
  },
  pleaseLoginText: {
    fontSize: commonStyles.thirdFontSize,
    color: colors.text,
    marginBottom: moderateVerticalScale(20),
    fontFamily: typo.sofiaBroRegular,
  },
  loginButton: {
    width: moderateScale(150),
  },
  container: {
    flex: 1,
    paddingHorizontal: commonStyles.marginHorizontal,
    backgroundColor: colors.white,
    alignItems: 'center',
    alignSelf: 'center',
    width: '100%',
    maxWidth: moderateScale(650),
    marginBottom: commonStyles.marginVertical * 3,
  },
  pleaseLoginContainer: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    gap: moderateVerticalScale(22),
    paddingHorizontal: moderateScale(60),
  },
  pleaseLoginImageText1: {
    fontSize: commonStyles.thirdFontSize,
    color: colors.text,
    fontFamily: typo.helvetica85Heavy,
    marginBottom: moderateVerticalScale(11),
    textAlign: 'center',
  },
  pleaseLoginImageText2: {
    fontSize: commonStyles.thirdFontSize,
    color: colors.text,
    fontFamily: typo.sofiaBroRegular,
    textAlign: 'center',
  },
  pleaseLoginImage: {
    width: moderateScale(100),
    height: moderateVerticalScale(100),
    resizeMode: 'contain',
    tintColor: colors.drift_wood,
  },
  pleaseLoginImageButton: {
    width: '50%',
  },
  editIcon: {
    height: moderateVerticalScale(30),
    width: moderateScale(30),
    resizeMode: 'contain',
    tintColor: colors.white,
  },
  item: {
    paddingHorizontal: commonStyles.marginHorizontal / 2,
  },

  addImage: {
    width: moderateScale(27),
    height: moderateVerticalScale(27),
    position: 'absolute',
    bottom: moderateVerticalScale(0),
    right: moderateScale(5),
  },
  camera: {
    width: moderateScale(35),
    height: moderateVerticalScale(35),
    resizeMode: 'contain',
  },
  image: {
    width: moderateScale(90),
    height: moderateVerticalScale(90),
    borderRadius: moderateScale(45),
    resizeMode: 'cover',
  },
  profileImgContainer: {
    position: 'absolute',
    zIndex: 99999999,
    width: '50%',
    flexDirection: 'row',
    justifyContent: 'center',
    top: '-6%',
    left: '25%',
  },
  overlay: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  modalContainer: {
    width: moderateScale(300),
    height: moderateVerticalScale(300),
    justifyContent: 'center',
    alignItems: 'center',
    overflow: 'hidden',
    backgroundColor: colors.black,
    borderRadius: moderateScale(150),
  },
  fullHeight: {
    flex: 1,
  },
  emptyViewTitle: {
    fontFamily: typo.sofiaBroRegular,
    fontSize: commonStyles.thirdFontSize,
  },
  actionsContainer: {position: 'absolute', bottom: '4%'},
  profileImage: {
    width: moderateScale(90),
    height: moderateVerticalScale(90),
    backgroundColor: colors.black,
    borderRadius: moderateScale(45),
    justifyContent: 'center',
    alignItems: 'center',
    overflow: 'hidden',
  },

  imageContainer: {
    backgroundColor: colors.white,
    borderRadius: moderateScale(150),
    padding: commonStyles.marginHorizontal / 3,
  },
});

Errorview.jsx

import React, {memo} from 'react';
import {useTranslation} from 'react-i18next';
import {StyleSheet, Text, View} from 'react-native';
import Button from './Button';
import {moderateVerticalScale} from 'react-native-size-matters/extend';
import {colors, typo} from '@common';
import {commonStyles} from '@utils/constants';

const ErrorView = ({children, hasError, onRetry, error}) => {
  const {t} = useTranslation();

  const generateErrorMsg = error => {
    switch (error?.originalStatus || error?.status) {
      case 'FETCH_ERROR':
        return t('check_your_internet_connection');
      case 502:
        return t('we_are_updating_our_services_thanks_for_your_patience');
      default:
        return error?.error;
    }
  };

  return hasError ? (
    <View style={styles.container}>
      <View style={styles.oopsContainer}>
        <Text style={styles.oops}>{t('oops')}</Text>
        <Text style={styles.wentWrong}>
          {generateErrorMsg(error) || t('something_went_wrong')}
        </Text>
      </View>
      <Button
        title={t('try_again')}
        onPress={onRetry}
        style={styles.tryAgain}
      />
    </View>
  ) : (
    children
  );
};

export default memo(ErrorView);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: colors.white,
    paddingHorizontal: commonStyles.marginHorizontal,
  },
  someThingWentWrong: {
    fontFamily: typo.sofiaBroBlack,
    fontSize: commonStyles.thirdFontSize,
    paddingBottom: moderateVerticalScale(25),
  },
  oopsContainer: {
    paddingBottom: moderateVerticalScale(24),
    gap: moderateVerticalScale(10),
  },
  oops: {
    fontFamily: typo.sofiaBroBlack,
    textAlign: 'center',
    fontSize: commonStyles.semiBiggerFontSize,
    color: colors.black,
  },
  wentWrong: {
    fontFamily: typo.sofiaBroRegular,
    textAlign: 'center',
    fontSize: commonStyles.semiBiggerFontSize,
    color: colors.black,
    lineHeight: commonStyles.secondaryLingHeight,
  },
  tryAgain: {
    backgroundColor: colors.main_red,
  },
});

Steps to reproduce

  1. open app
  2. navigate to profile stack
  3. Use RTK Query to initiate a network request (e.g., useQuery)
  4. Observe that the query returns a TypeError: Network request failed randomly randomly instead of executing successfully.

React Native Version

0.75.4

Affected Platforms

Runtime - iOS

Output of npx react-native info

System:
  OS: macOS 12.7.6
  CPU: (8) x64 Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
  Memory: 53.96 MB / 16.00 GB
  Shell:
    version: 5.8.1
    path: /bin/zsh
Binaries:
  Node:
    version: 20.15.0
    path: ~/.nvm/versions/node/v20.15.0/bin/node
  Yarn:
    version: 4.5.0
    path: ~/.nvm/versions/node/v20.15.0/bin/yarn
  npm:
    version: 10.7.0
    path: ~/.nvm/versions/node/v20.15.0/bin/npm
  Watchman:
    version: 2024.07.15.00
    path: /usr/local/bin/watchman
Managers:
  CocoaPods:
    version: 1.15.2
    path: /usr/local/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 21.4
      - iOS 16.0
      - macOS 12.3
      - tvOS 16.0
      - watchOS 9.0
  Android SDK:
    API Levels:
      - "25"
      - "28"
      - "30"
      - "31"
      - "33"
      - "34"
      - "35"
    Build Tools:
      - 24.0.0
      - 24.0.1
      - 24.0.2
      - 24.0.3
      - 30.0.2
      - 30.0.3
      - 33.0.0
      - 33.0.1
      - 34.0.0
      - 35.0.0
    System Images:
      - android-26 | Google Play Intel x86 Atom
      - android-34 | Intel x86_64 Atom
      - android-34 | Google APIs Intel x86_64 Atom
    Android NDK: Not Found
IDEs:
  Android Studio: 2024.1 AI-241.18034.62.2411.12169540
  Xcode:
    version: 14.0/14A309
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.11
    path: /usr/bin/javac
  Ruby:
    version: 2.6.10
    path: /usr/bin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.3.1
    wanted: 18.3.1
  react-native:
    installed: 0.75.4
    wanted: 0.75.4
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: true
  newArchEnabled: false

Stacktrace or Logs

TypeError: Network request failed randomly

Reproducer

commercial app

Screenshots and Videos

Activity

  1. changed the title [-]TypeError: Network request failed randomly[/-] [+]TypeError: Network request failed randomly in IOS[/+] on Jan 29, 2025
  2. react-native-bot commented on Jan 29, 2025

    @react-native-bot
    Collaborator

    Warning

    Missing reproducer: We could not detect a reproducible example in your issue report. Please provide either:

  3. Nader-CS commented on Jan 29, 2025

    @Nader-CS
    Author

    please any updates , this is a critical issue.

  4. sarthak-playvision commented on Jan 29, 2025

    @sarthak-playvision

    Hey @Nader-CS,

    Could you please share a reproducible example for this issue? You can use this template: Reproducer Template.

    Additionally, based on the output of npx react-native info, it looks like you are currently using the old architecture. Would you mind checking if the issue persists when using the new architecture as well?

  5. Nader-CS commented on Feb 2, 2025

    @Nader-CS
    Author

    unfortunately , this is commerical app and also can't re-produce it :( @sarthak-d11

  6. 7 remaining items

  7. renay007 commented on Sep 11, 2025

    @renay007

    Thanks!

    Do you mind sharing your code snippet for it?

    For extra context, I also have a web app built in React using the same RTK query used in my React Native app and it happens on iOS or Android phones using the web app.

  8. renay007 commented on Sep 11, 2025

    @renay007

    Alright - I believe I have found a consistent way of reproducing this error on my end. I slowed my network connection, put app in background for 30 seconds while my RTK query is polling at an interval of 5 seconds.

    1. Launch your iOS app in a simulator
    2. Depending on the Xcode version you're using, download from Apple's website the Additional_Tools_for_Xcode_[version]. In my case, it was Additional_Tools_for_Xcode_16.2.
    3. Double click on the .dmg file and go to the Hardware folder and double click on the Network Link Conditioner.prefPane file to install the Network Link Conditioner application.
    4. One you have the Network Link Conditioner opened, select the Very Bad Network profile
    5. Set any RTK Query request using the useQuery hook and set pollingInterval to 5 seconds.
    6. If you're using Reactotron, filter out the logs to only see API requests.
    7. Wait to see one request come through. Count to 4 - 5 seconds and right before the next request comes in, put the app in background and count to 30 - 35 seconds.
    8. Open the app and you will that RTK query will fail almost every time if you time it well.

    I only used the network link conditioner to be able to repeat it almost every time but it's not needed.

    Since under the hood I'm using axios to fetch the requests, here's what gets returned every single time with a status code of 0.

    {
      "message": "timeout of 30000ms exceeded",
      "name": "AxiosError",
      "description": "undefined",
      "number": "undefined",
      "fileName": "undefined",
      "lineNumber": "undefined",
      "columnNumber": "undefined",
      "code": "ECONNABORTED",
      "status": "undefined",
      "config": {
        "timeout": "30000"
      }
    }

    My current solution now is to listen to this specific error code and instead of showing an error, I show a loader since I'm polling and API will be trying the request again.

    Hope this was helpful!!

  9. abitling commented on Sep 12, 2025

    @abitling

    Thanks!

    Do you mind sharing your code snippet for it?

    For extra context, I also have a web app built in React using the same RTK query used in my React Native app and it happens on iOS or Android phones using the web app.

    I cannot share the code snippet here, but all I can say is, I have just delayed the function call by 500ms usingsetTimeout, This function is responsible to initiate the RTK Query to fetch data. I my case I am not performing polling requests, I understand, it seem to be difficult to delay a polling request.

    I strongly believe, this should be caused by the underlying Fetch API. Can somebody try to reproduce this with a bare RN project and Fetch API so that we can eliminate the possibility of RTK Query causing the issue.

  10. renay007 commented on Sep 12, 2025

    @renay007

    Thanks!
    Do you mind sharing your code snippet for it?
    For extra context, I also have a web app built in React using the same RTK query used in my React Native app and it happens on iOS or Android phones using the web app.

    I cannot share the code snippet here, but all I can say is, I have just delayed the function call by 500ms usingsetTimeout, This function is responsible to initiate the RTK Query to fetch data. I my case I am not performing polling requests, I understand, it seem to be difficult to delay a polling request.

    I strongly believe, this should be caused by the underlying Fetch API. Can somebody try to reproduce this with a bare RN project and Fetch API so that we can eliminate the possibility of RTK Query causing the issue.

    I see. You’re probably using lazy query in that case and you’re delaying your function call by 500ms.

    Based on what I experienced, I think in your case, if you were to perfectly time the request before you put the app in background mode, the issue could still happen.

    I strongly believe that the issue has to do with the app going to background while the request is in flight and after 30 seconds or so, usually the OS itself will kill any TCP connection that was established when the app was open. So I think if the fetch library or axios throws an error ECONNABORTED, I think it’s ok and it’s expected.

    So I’m thinking, maybe there’s nothing to fix here if it’s happening only by temporarily putting the phone in background.

    If it’s happening while the app is open all the time, then that’s not the issue I’m experiencing.

    Take a look at the other link shared by OP: reduxjs/redux-toolkit#4825 (comment)

    It seems that is issue is only happening by putting the app in background mode.

  11. abitling commented on Sep 12, 2025

    @abitling

    Thanks!
    Do you mind sharing your code snippet for it?
    For extra context, I also have a web app built in React using the same RTK query used in my React Native app and it happens on iOS or Android phones using the web app.

    I cannot share the code snippet here, but all I can say is, I have just delayed the function call by 500ms usingsetTimeout, This function is responsible to initiate the RTK Query to fetch data. I my case I am not performing polling requests, I understand, it seem to be difficult to delay a polling request.
    I strongly believe, this should be caused by the underlying Fetch API. Can somebody try to reproduce this with a bare RN project and Fetch API so that we can eliminate the possibility of RTK Query causing the issue.

    I see. You’re probably using lazy query in that case and you’re delaying your function call by 500ms.

    Based on what I experienced, I think in your case, if you were to perfectly time the request before you put the app in background mode, the issue could still happen.

    I strongly believe that the issue has to do with the app going to background while the request is in flight and after 30 seconds or so, usually the OS itself will kill any TCP connection that was established when the app was open. So I think if the fetch library or axios throws an error ECONNABORTED, I think it’s ok and it’s expected.

    So I’m thinking, maybe there’s nothing to fix here if it’s happening only by temporarily putting the phone in background.

    If it’s happening while the app is open all the time, then that’s not the issue I’m experiencing.

    Take a look at the other link shared by OP: reduxjs/redux-toolkit#4825 (comment)

    It seems that is issue is only happening by putting the app in background mode.

    Its not about perfectly timing the app state change.

    In my case its not a polling request, its a mandatory network request which fetches the necessary information from the server (something like refreshing the subscription information for the user from server as soon as app comes back to Foreground). I need to make this network request every time app comes back to foreground.

    I do not see any strong reason why OS itself would kill the TCP connection. Especially when the app is put back to foreground from background. I would term this as a bug instead of expected behaviour.

    Let me know if I am missing on any necessary information.

  12. renay007 commented on Sep 12, 2025

    @renay007

    Thanks!
    Do you mind sharing your code snippet for it?
    For extra context, I also have a web app built in React using the same RTK query used in my React Native app and it happens on iOS or Android phones using the web app.

    I cannot share the code snippet here, but all I can say is, I have just delayed the function call by 500ms usingsetTimeout, This function is responsible to initiate the RTK Query to fetch data. I my case I am not performing polling requests, I understand, it seem to be difficult to delay a polling request.
    I strongly believe, this should be caused by the underlying Fetch API. Can somebody try to reproduce this with a bare RN project and Fetch API so that we can eliminate the possibility of RTK Query causing the issue.

    I see. You’re probably using lazy query in that case and you’re delaying your function call by 500ms.
    Based on what I experienced, I think in your case, if you were to perfectly time the request before you put the app in background mode, the issue could still happen.
    I strongly believe that the issue has to do with the app going to background while the request is in flight and after 30 seconds or so, usually the OS itself will kill any TCP connection that was established when the app was open. So I think if the fetch library or axios throws an error ECONNABORTED, I think it’s ok and it’s expected.
    So I’m thinking, maybe there’s nothing to fix here if it’s happening only by temporarily putting the phone in background.
    If it’s happening while the app is open all the time, then that’s not the issue I’m experiencing.
    Take a look at the other link shared by OP: reduxjs/redux-toolkit#4825 (comment)
    It seems that is issue is only happening by putting the app in background mode.

    Its not about perfectly timing the app state change.

    In my case its not a polling request, its a mandatory network request which fetches the necessary information from the server (something like refreshing the subscription information for the user from server as soon as app comes back to Foreground). I need to make this network request every time app comes back to foreground.

    I do not see any strong reason why OS itself would kill the TCP connection. Especially when the app is put back to foreground from background. I would term this as a bug instead of expected behaviour.

    Let me know if I am missing on any necessary information.

    I see what you’re saying. Our use case is probably different. In my case, I understand why the error happens and I think it makes sense. For your use case, if you’re fetching when app comes to foreground and it is throwing an error prematurely unless you put that delay, that’s probably a bug.

  13. Nader-CS commented on Oct 13, 2025

    @Nader-CS
    Author

    any update about this ?

  14. Nader-CS commented on Oct 13, 2025

    @Nader-CS
    Author

    I realized something new — most of the API failures are related to the polling interval prop.

  15. react-native-bot commented on Apr 12, 2026

    @react-native-bot
    Collaborator

    This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

  16. added
    StaleThere has been a lack of activity on this issue and it may be closed soon.
    and removed
    StaleThere has been a lack of activity on this issue and it may be closed soon.
    on Apr 12, 2026
  17. react-native-bot commented on Oct 10, 2026

    @react-native-bot
    Collaborator

    This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

  18. added
    StaleThere has been a lack of activity on this issue and it may be closed soon.
    on Oct 10, 2026
  19. Nader-CS commented on Oct 10, 2026

    @Nader-CS
    Author

    still exist

  20. removed
    StaleThere has been a lack of activity on this issue and it may be closed soon.
    on Oct 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs: AttentionIssues where the author has responded to feedback.Needs: ReproThis issue could be improved with a clear list of steps to reproduce the issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions