reactotron: iOS Release Build app crash on real device

Terminating app due to uncaught exception 'RCTFatalException: Unhandled JS Exception: Error: invalid host, js engine: hermes', reason: 'Unhandled JS Exception: Error: invalid host, js engine: hermes

App crashing in ios release mode. Refer for detail: https://github.com/facebook/hermes/issues/1228

About this issue

  • Original URL
  • State: closed
  • Created 6 months ago
  • Reactions: 7
  • Comments: 27 (3 by maintainers)

Commits related to this issue

Most upvoted comments

Reactotron should not be loaded in production. Read more about why here. https://docs.infinite.red/reactotron/tips/#running-in-production

Consider adding eslint-plugin-reactotron to your project to help ensure that any reactotron calls are getting hidden behind a __DEV__ flag.

Trouble shooting checklist:

  • ensure Reactotron is only loaded behind __DEV__ flag
  • use require('ReactotronConfig.ts') instead of import('ReactotronConfig') because import is hoisted outside of __DEV__ blocks.

✅ Closing this issue since below things are working properly, just follow below and then delete nodemodules,lock files, pods etc and reinstall again:

  1. Libraries version(downgrade only if below steps do not work):
    "reactotron-react-native": "5.0.3",
    "reactotron-redux": "3.1.3",
  1. ReactotronConfig.js
import Reactotron, { networking } from 'reactotron-react-native';
import { reactotronRedux } from 'reactotron-redux';
import AsyncStorage from '@react-native-async-storage/async-storage';

Reactotron.configure({ name: 'app_name' })
  .setAsyncStorageHandler(AsyncStorage)
  .useReactNative()
  .use(reactotronRedux()) //  <- here i am!
  .use(networking())
  .connect();

// patch console.log to send log to reactotron
const yeOldeConsoleLog = console.log;
console.log = (...args) => {
  yeOldeConsoleLog(...args);
  Reactotron.display({
    name: 'CONSOLE.LOG',
    value: args,
    preview: args.length > 0 && typeof args[0] === 'string' ? args[0] : null,
  });
};

export default Reactotron;
  1. store.js
import AsyncStorage from '@react-native-async-storage/async-storage';
import { combineReducers, configureStore } from '@reduxjs/toolkit';
import { persistReducer, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER } from 'redux-persist';
import userSlice from './slices/userSlice';
import nonPersistedSlice from './slices/nonPersistedSlice';

const persistConfig = {
  key: 'root',
  version: 1,
  storage: AsyncStorage,
  blacklist: ['nonPersistedSlice'], // these reduce will not persist data
  whitelist: ['userSlice'], // these reduce will persist data
};
const reducer = combineReducers({
  userSlice,
  nonPersistedSlice,
});
const persistedReducer = persistReducer(persistConfig, reducer);

const getEnhancers = (getDefaultEnhancers) => {
  if (process.env.NODE_ENV === 'development') {
    const reactotron = require('../helpers/ReactotronConfig').default;
    return getDefaultEnhancers().concat(reactotron.createEnhancer());
  }
  return getDefaultEnhancers();
};

const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) => getDefaultMiddleware(),
  enhancers: getEnhancers,
});

export default store;

Downgrading reactotron-react-native to 5.0.3 and removing host from the configuration worked for us.

Same here. In my case only on iOS Release Mode

The problem started to happen in version 5.0.4 of reactotron-react-native. Using version 5.0.3 the crash does not occur. Comparing the versions, it can be seen that the getHost routine in the file /reactotron-react-native/src/reactotron-react-native.ts uses a simplified version, which works for Expo applications, but in iOS builds in release mode this new version uses the URI of the embedded bundle.

Example: using the code NativeModules?.SourceCode?.getConstants().scriptURL in release mode you get something like file:///private/var/containers/Bundle/Application/38A07257-A8E8-4565-BBE6-6B874A82A47B/app_name.app /main.jsbundle The new getHost routine will extract “private” and will try to use it as a host, which generates the “invalid host” exception

@Ajmal0197

Your solution works. Thank you for saving my day

This is what work for us with the latest version 5.1.3:

import createSagaMiddleware from 'redux-saga';
import { persistStore } from 'redux-persist';
import { configureStore } from '@reduxjs/toolkit';

import rootReducer from './reducers';
import rootSaga from './sagas';

const shouldLoadDebugger = (__DEV__ && !process.env.JEST_WORKER_ID);
const reactotronInstance = shouldLoadDebugger ? require('../reactotron.config').default : null;

// Configure saga and root (combined) reducer, along with Reactotron
const sagaMiddleware = createSagaMiddleware(shouldLoadDebugger ? { sagaMonitor: reactotronInstance.createSagaMonitor() } : {});
const store = configureStore({
    reducer: rootReducer,
    middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false }).concat([sagaMiddleware]),
    enhancers: shouldLoadDebugger ? [reactotronInstance.createEnhancer()] : [],
});

const persistor = persistStore(store, null);

sagaMiddleware.run(rootSaga);

if (__DEV__ && module.hot) {
    module.hot.accept('./src/reducers', () => store.replaceReducer(rootReducer));
}

export { store, persistor };

@pokey the real issue is caused by running Reactotron in production, upgrading to 5.0.5 seemed highlight this issue for some users.

I put together a checklist here for how to ensure that Reactotron is not getting loaded in your app and a helpful linting rule to prevent it in the future: https://github.com/infinitered/reactotron/issues/1398#issuecomment-1899058678

After some tinkering and researching other projects, I finally figured out a configuration that’s working for me using Redux Toolkit v2:

// ReactotronConfig.ts
import Reactotron from 'reactotron-react-native';
import { reactotronRedux } from 'reactotron-redux';

const reactotron = Reactotron.configure({ name: '[NAME OF YOUR APP]' })
  .useReactNative()
  .use(reactotronRedux())
  .connect(); 

export default reactotron; 
// store.ts
import { configureStore, EnhancedStore } from '@reduxjs/toolkit';
import { setupListeners } from '@reduxjs/toolkit/query';

export const store = configureStore({
  reducer: {
    [YOUR REDUCERS]
  },
  middleware: getDefaultMiddleware =>
    getDefaultMiddleware().concat([YOUR MIDDLEWARE IF YOU HAVE ANY]),
  // Note: Enhancers have to go after middleware
  enhancers: getDefaultEnhancers =>
    __DEV__
      ? getDefaultEnhancers().concat(
          require('../ReactotronConfig').default.createEnhancer()
        )
      : getDefaultEnhancers(),
});

setupListeners(store.dispatch);

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

I hope that works for you too! I updated my tsconfig compilerOptions to include "module": "Node16", "moduleResolution": "Node16", "esModuleInterop": true, but couldn’t get Reactotron to come insto store.ts with a type other than any.

Downgrade reactotron-react-native to 5.0.3 worked for me too. I cleared node_modules and installed pods again. I use host configuration and didn’t have to remove it. I don’t have reactotron-redux

In my case, I also had to downgrade reactotron-redux to version 3.1.3.

Same here, and this problem started today, the lib release was about 20 hours ago…

Hi @GSFZamai Yes, i have tried it but still in the production the same thing happens…

I had to remove node_modules, clear metro and XCode cache to work locally after downgrade