Skip to content

Image assets silently fail to render in Yarn workspace monorepo with React Native 0.81.4 #1599

@sibe7691

Description

@sibe7691

🐛 Image assets silently fail to render in Yarn workspace monorepo with React Native 0.81.4

When using Yarn 4 workspaces in a monorepo, React Native 0.81.4 fails to render static image assets that live in another workspace.
JavaScript and TypeScript modules import correctly, but any require()d image (e.g. .png, .jpg, .svg) never appears at runtime. Metro starts normally and shows no visible error, yet the images do not render.

Environment

  • React Native: 0.81.4
  • React: 19.1.0
  • Yarn: 4.x (workspaces)
  • Node: 20.x
  • OS: macOS 14 (M3 Pro)
  • Bundler: Metro (default)

Relevant dependencies

{
  "@react-native/metro-config": "0.81.4",
  "@react-native/babel-preset": "0.81.4",
  "@react-native/typescript-config": "0.81.4",
  "react-native-svg-transformer": "1.5.1",
  "react-native": "0.81.4",
  "react": "19.1.0"
}

Expected behavior

Metro/React Native should correctly resolve and bundle static image assets exported from shared workspace packages — the same way it handles JS modules.

Actual behavior

When importing images from another workspace (e.g., @rb-oxygen/assets), the app runs without any build or runtime error, but the image simply does not appear.
The bundler shows no warnings, and React Native logs are clean.
However, Console.app on macOS shows repeated asset fetch cancellations when attempting to resolve the image from a path outside Metro’s asset root:

default 22:51:30.221651+0200 rbApp [C1142 91F51773-BDF4-4AA2-AB73-DE1143360C12 Hostname#df48400c:8081 tcp, url: http://localhost:8081/assets/../../packages/assets/images/logo.png, definite, attribution: developer] cancel
default 22:51:30.221707+0200 rbApp [C1142 91F51773-BDF4-4AA2-AB73-DE1143360C12 Hostname#df48400c:8081 tcp, url: http://localhost:8081/assets/../../packages/assets/images/logo.png, definite, attribution: developer] cancelled

This suggests Metro is attempting to resolve the image via a relative path outside the app’s asset root, then silently cancels the request.

Monorepo layout

/monorepo
  /packages
    /mobile       (React Native app)
    /assets       (shared images)
    /molecules    (shared UI components)

Shared package (image exports)

// packages/assets/icons.ts
export const icons = {
  logo: require('./images/logo.png'),
  avatar: require('./images/avatar.png'),
}

App usage

// packages/mobile/App.tsx
import React from 'react'
import { Image } from 'react-native'
import { icons } from '@rb-oxygen/assets/icons'

export const App = () => (
  <Image source={icons.logo} style={{ width: 64, height: 64 }} />
)

When running the app with:

yarn start
yarn ios

The app builds and runs, but the image renders as an empty space.
No visible errors appear in Metro or the terminal.

Metro configuration

// packages/mobile/metro.config.js
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config')
const path = require('path')

const defaultConfig = getDefaultConfig(__dirname)
const { assetExts, sourceExts } = defaultConfig.resolver

const workspaceRoot = path.resolve(__dirname, '../..')

const customConfig = {
  cacheVersion: '@rb-oxygen/mobile',
  watchFolders: [
    workspaceRoot,
    __dirname,
    path.resolve(workspaceRoot, 'packages'),
    path.resolve(workspaceRoot, 'features'),
  ],
  transformer: {
    babelTransformerPath: require.resolve('react-native-svg-transformer'),
  },
  resolver: {
    assetExts: [...assetExts.filter(ext => ext !== 'svg'), 'lottie'],
    sourceExts: [...sourceExts, 'cjs', 'mjs', 'svg', 'ts', 'tsx'],
  },
}

module.exports = mergeConfig(defaultConfig, customConfig)

Troubleshooting attempts

  • Verified all symlinked workspace paths resolve correctly under Yarn 4
  • Added all workspace roots to watchFolders
  • Extended resolver.assetExts and sourceExts
  • Confirmed that JS/TS imports across workspaces work perfectly
  • Tried both direct require() calls and re-exported imports

The issue persists: all images fail silently with no errors in Metro logs, only the Console.app network cancellations shown above.


Additional context

  • This setup worked correctly in earlier React Native versions (<0.80).
  • The issue appears related to Metro 0.81+ handling of asset roots in Yarn workspaces.

Question

Is there an official or recommended way to configure Metro or React Native 0.81.4 so that static image assets from other Yarn workspace packages resolve and render correctly?
Am I missing something else since the upgrade?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions