Metro version: 0.84.4
Expo SDK version: 57.0.11
Node.js version: 22.16.0
Description
When Metro's Bundler fails to construct its Transformer (e.g. due to a MODULE_NOT_FOUND error in getTransformCacheKey), the actual error is silently caught and swallowed. As a result, this._transformer remains undefined, and any subsequent bundle request produces a completely unrelated and misleading error:
TypeError: Cannot read properties of undefined (reading 'transformFile')
at Bundler.transformFile (metro/src/Bundler.js:55:30)
This makes debugging extremely difficult because the real cause of the failure (e.g. a missing Babel preset) is never surfaced to the developer.
Root Cause
In metro/src/Bundler.js, the _initializedPromise is defined as:
this._initializedPromise = this._depGraph
.ready()
.then(() => {
this._transformer = new _Transformer.default(config, { ... });
})
.catch((error) => {
console.error("Failed to construct transformer: ", error);
config.reporter.update({ type: "transformer_load_failed", error });
// Error is NOT re-thrown promise resolves as undefined
});
The catch handler logs the error but does not re-throw it, so _initializedPromise resolves successfully even when _transformer was never assigned. When Bundler.transformFile later calls await this.ready() (which awaits _initializedPromise), it returns without error — and then immediately crashes on this._transformer.transformFile(...).
Expected Behavior
The real error (e.g. Cannot find module 'babel-preset-expo') should propagate and be shown to the developer immediately, either as a clear startup failure or as the error message in the bundling output.
Metro version: 0.84.4
Expo SDK version: 57.0.11
Node.js version: 22.16.0
Description
When Metro's
Bundlerfails to construct itsTransformer(e.g. due to aMODULE_NOT_FOUNDerror ingetTransformCacheKey), the actual error is silently caught and swallowed. As a result,this._transformerremainsundefined, and any subsequent bundle request produces a completely unrelated and misleading error:This makes debugging extremely difficult because the real cause of the failure (e.g. a missing Babel preset) is never surfaced to the developer.
Root Cause
In
metro/src/Bundler.js, the_initializedPromiseis defined as:The
catchhandler logs the error but does not re-throw it, so_initializedPromiseresolves successfully even when_transformerwas never assigned. WhenBundler.transformFilelater callsawait this.ready()(which awaits_initializedPromise), it returns without error — and then immediately crashes onthis._transformer.transformFile(...).Expected Behavior
The real error (e.g.
Cannot find module 'babel-preset-expo') should propagate and be shown to the developer immediately, either as a clear startup failure or as the error message in the bundling output.