emotion-js/emotion · error · Error

[ThemeProvider] Please return an object from your theme…

Error message

[ThemeProvider] Please return an object from your theme function, i.e. theme={() => ({})}!

What it means

@emotion/react's ThemeProvider getTheme() validates that the resolved theme is a non-null, non-array object. When the theme prop is a function, the function's return value (mergedTheme) is checked; if the function returns null, undefined, a primitive, or an array, this error is thrown in development. It exists because downstream emotion code destructures and spreads the theme and would otherwise fail with confusing errors.

Solutions

  1. Make the theme function always return a plain object, e.g. theme={() => ({ ...myTheme })}
  2. Guard inside the function: return loadedTheme ?? {} instead of null/undefined
  3. If the theme is a static object, pass it directly (theme={myTheme}) rather than wrapping it in a function that may return non-objects
  4. Ensure the return value is not an array; spread arrays into an object or restructure the theme

Example fix

// before
<ThemeProvider theme={() => config?.theme ?? null}>
// after
<ThemeProvider theme={() => config?.theme ?? {}}>
Defensive patterns

Strategy: validation

Validate before calling

const resolved = typeof themeFn === 'function' ? themeFn(outerTheme) : themeFn
if (resolved == null || typeof resolved !== 'object' || Array.isArray(resolved)) {
  throw new TypeError('theme function must return a plain object')
}

Type guard

function isPlainTheme(t: unknown): t is Record<string, unknown> {
  return t != null && typeof t === 'object' && !Array.isArray(t)
}

Try / catch

try {
  render(<ThemeProvider theme={makeTheme}>{children}</ThemeProvider>)
} catch (e) {
  if (e.message.includes('[ThemeProvider]')) {
    console.error('theme function returned a non-object; falling back to {}')
    render(<ThemeProvider theme={{}}>{children}</ThemeProvider>)
  } else throw e
}

Prevention

When it happens

Trigger: Passing theme={fn} to <ThemeProvider> where fn returns null, undefined, a primitive (string/number), or an array; e.g. theme={() => null} or a factory that conditionally returns nothing. Only thrown when isDevelopment.

Common situations: Theme factory functions that early-return null when config isn't loaded yet; refactored theme objects accidentally turned into arrays; async data that hasn't resolved so the factory returns undefined.

Related errors


AI-assisted analysis of emotion-js/emotion@b882bcba85 (2026-09-02). Data as JSON: /api/errors/dbe9dbf6e2753d61. Report an issue: GitHub.

Appendix: source

Thrown at packages/react/src/theming.tsx:42

if (isDevelopment) {
  ThemeContext.displayName = 'EmotionThemeContext'
}

export const useTheme = () => React.useContext(ThemeContext)

const getTheme = (
  outerTheme: Theme,
  theme: Partial<Theme> | ((theme: Theme) => Theme)
): Theme => {
  if (typeof theme === 'function') {
    const mergedTheme = theme(outerTheme)
    if (
      isDevelopment &&
      (mergedTheme == null ||
        typeof mergedTheme !== 'object' ||
        Array.isArray(mergedTheme))
    ) {
      throw new Error(
        '[ThemeProvider] Please return an object from your theme function, i.e. theme={() => ({})}!'
      )
    }
    return mergedTheme
  }
  if (
    isDevelopment &&
    (theme == null || typeof theme !== 'object' || Array.isArray(theme))
  ) {
    throw new Error(
      '[ThemeProvider] Please make your theme prop a plain object'
    )
  }

  return { ...outerTheme, ...theme }
}

let createCacheWithTheme = /* #__PURE__ */ weakMemoize((outerTheme: Theme) => {

View on GitHub (pinned to b882bcba85)