Skip to main content
If you’re using Vite.js with React and the Dynamic SDK, connecting MetaMask via the QR code flow (when the browser extension is not installed) may fail on the Vite dev server with errors like these in your console:
[MetaMaskEvmWalletConnector] getAddress failed: TypeError: PrivateKey is not a constructor
or
TypeError: Cannot read properties of undefined (reading 'create')
    at ... SessionStore ...
This happens because Vite’s dependency pre-bundling (esbuild) cannot generate named exports for two CommonJS packages that MetaMask’s QR connection flow depends on:
  • @metamask/mobile-wallet-protocol-core assigns its exports at the end of a minified file, a pattern esbuild can’t statically analyze — so named imports like SessionStore come back undefined.
  • eciesjs is loaded through a dynamic import(), and esbuild emits dynamic-import chunks for CommonJS dependencies with only a default export — so PrivateKey comes back undefined.
This only affects the dev server; production builds bundle CommonJS correctly.

Fix via vite.config.js

Two changes are needed: list eciesjs in optimizeDeps.include, and alias @metamask/mobile-wallet-protocol-core to a small ESM shim. First, create the shim file at src/shims/metamask-mobile-wallet-protocol-core.js:
// Re-exports the CJS package's members as explicit named ESM exports,
// since esbuild can't statically detect them during pre-bundling.
import * as cjsModule from '../../node_modules/@metamask/mobile-wallet-protocol-core/dist/index.js';

export const {
  BaseClient,
  ClientState,
  CONNECTION_MODES,
  CryptoError,
  DEFAULT_SESSION_TTL,
  ErrorCode,
  isValidConnectionMode,
  ProtocolError,
  SessionError,
  SessionStore,
  timingSafeEqual,
  TransportError,
  WebSocketTransport,
} = cjsModule;

export default cjsModule;
Then update vite.config.js:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import * as path from 'path';

export default defineConfig({
  plugins: [react()],
  optimizeDeps: {
    // eciesjs is consumed via a dynamic import inside MetaMask's connection flow;
    // listing it as an explicit entry makes esbuild generate proper named exports
    include: ['eciesjs'],
  },
  resolve: {
    alias: {
      '@metamask/mobile-wallet-protocol-core': path.resolve(
        __dirname,
        'src/shims/metamask-mobile-wallet-protocol-core.js',
      ),
    },
  },
});
The shim must import the package through its file path (node_modules/...) rather than the bare package name — otherwise the alias would rewrite the shim’s own import. Adjust the relative path to match where your shim file lives.