mihomo-party-org/clash-party · error · Error

useAppConfig must be used within an AppConfigProvider

Error message

useAppConfig must be used within an AppConfigProvider

What it means

useAppConfig reads AppConfigContext, created with React.createContext(undefined). If no <AppConfigProvider> (or equivalent Provider supplying AppConfigContextType) is present above the caller, the context is undefined and the hook throws 'useAppConfig must be used within an AppConfigProvider'. It enforces that app configuration is only read through a properly mounted provider.

Source

Thrown at src/renderer/src/hooks/use-app-config.tsx:58

    },
    [mutate, t]
  )

  return (
    <AppConfigContext.Provider
      value={{ appConfig: config, mutateAppConfig: mutate, patchAppConfig }}
    >
      {children}
    </AppConfigContext.Provider>
  )
}

const AppConfigContext = React.createContext<AppConfigContextType | undefined>(undefined)

export const useAppConfig = (): AppConfigContextType => {
  const context = React.useContext(AppConfigContext)
  if (!context) {
    throw new Error('useAppConfig must be used within an AppConfigProvider')
  }
  return context
}

View on GitHub (pinned to 911e090537)

Solutions

  1. Mount <AppConfigProvider> at the top of the app (root entry) so all consumers are descendants.
  2. Ensure the hook and provider are imported from the same module (no duplicate bundle copies).
  3. In tests/Storybook, wrap the component in the provider or a decorator.
  4. If a sane default exists, give createContext a default value instead of undefined.

Example fix

// before
createRoot(document.getElementById('root')!).render(<App />)
// after
createRoot(document.getElementById('root')!).render(
  <AppConfigProvider>
    <App />
  </AppConfigProvider>
)
Defensive patterns

Strategy: try-catch

Validate before calling

// wrap the app root
createRoot(rootEl).render(<AppConfigProvider><App /></AppConfigProvider>)

Try / catch

let appConfig
try {
  appConfig = useAppConfig()
} catch {
  appConfig = { config: defaultAppConfig, patchAppConfig: async () => {} }
}

Prevention

When it happens

Trigger: Calling useAppConfig() in a component rendered outside the AppConfig provider tree (root layout missing the provider, a portal/modal escaping the tree, or a plain TS module invoking the hook); duplicate module instances splitting provider and consumer contexts.

Common situations: Adding a new settings page and forgetting to add the provider at the app root; Storybook/tests rendering the component bare; refactors that moved the provider below a route that still consumes the hook.

Related errors


AI-assisted analysis of mihomo-party-org/clash-party@911e090537 (2026-08-30). Data as JSON: /api/errors/68aeee5e0a9de5e3. Report an issue: GitHub.