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

useConfig must be used within Provider

Error message

useConfig must be used within Provider

What it means

createConfigContext() is a factory that builds a typed React context plus a useConfig hook. The generated hook throws 'useConfig must be used within Provider' when useContext returns undefined — i.e. the calling component has no corresponding <Provider> above it in the tree. It is a React context-contract violation error.

Source

Thrown at src/renderer/src/hooks/create-config-context.tsx:40

    const { data: config, mutate } = useSWR(swrKey, fetcher)

    useEffect(() => {
      const handler = (): void => {
        mutate()
      }
      window.electron.ipcRenderer.on(ipcEvent, handler)
      return () => {
        window.electron.ipcRenderer.removeListener(ipcEvent, handler)
      }
    }, [mutate])

    return <Context.Provider value={{ config, mutate }}>{children}</Context.Provider>
  }

  const useConfig = (): ConfigContextValue<T> => {
    const context = useContext(Context)
    if (!context) {
      throw new Error(`useConfig must be used within Provider`)
    }
    return context
  }

  return { Provider, useConfig, Context }
}

interface ActionOptions {
  errorKey: string
  updateTray?: boolean
}

export function useConfigAction<T>(
  mutate: KeyedMutator<T>,
  action: () => Promise<void>,
  options: ActionOptions
): () => Promise<void> {
  const { t } = useTranslation()

View on GitHub (pinned to 911e090537)

Solutions

  1. Wrap the consuming component (or the route/layout) with the Provider produced by the same createConfigContext call.
  2. Check import paths so the hook and the Provider come from one module instance (avoid deep imports that duplicate the module).
  3. In tests, mount the component inside the provider or mock the context.
  4. If a default is acceptable, pass a default value to createContext instead of undefined.

Example fix

// before
export default function Panel() {
  const { config } = useSysproxyConfig() // throws outside provider
// after
export default function App() {
  return (
    <SysproxyConfigProvider>
      <Panel />
    </SysproxyConfigProvider>
  )
}
Defensive patterns

Strategy: try-catch

Validate before calling

// at app root, ensure provider mounts before routes render
if (!document.querySelector('[data-config-provider]')) console.warn('Provider not mounted yet')

Try / catch

// recommended: fail fast in dev, default in prod
function useConfigSafe() {
  try {
    return useConfig()
  } catch {
    if (import.meta.env.DEV) throw new Error('useConfig must be used within Provider')
    return { config: defaultConfig, mutate: () => {} }
  }
}

Prevention

When it happens

Trigger: Calling useXxxConfig() (generated by createConfigContext) from a component rendered outside <Provider> for that context; importing the hook in a utility/module executed outside React rendering; two separate instances of the module (duplicate bundling) so hook and provider use different context instances.

Common situations: A shared component moved to a page/layout that forgot to wrap with the provider; tests rendering a component without the provider; monorepo/bundler duplicate-module issues where provider and consumer resolve different copies of the file.

Related errors


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