{"record":{"id":"83d623f00150aced","repo":"facebook/docusaurus","slug":"hook-hookname-is-called-outside-the-titleforma","errorCode":null,"errorMessage":"Hook ${hookName} is called outside the <TitleFormatterProvider>.","messagePattern":"Hook (.+?) is called outside the <TitleFormatterProvider>\\.","errorType":"exception","errorClass":"ReactContextError","httpStatus":null,"severity":"error","filePath":"packages/docusaurus-theme-common/src/utils/titleFormatterUtils.tsx","lineNumber":95,"sourceCode":"\nexport function TitleFormatterProvider({\n  formatter,\n  children,\n}: {\n  children: ReactNode;\n  formatter: TitleFormatterFnWithDefault;\n}): ReactNode {\n  return (\n    <TitleFormatterContext.Provider value={formatter}>\n      {children}\n    </TitleFormatterContext.Provider>\n  );\n}\n\nfunction useTitleFormatterContext() {\n  const value = useContext(TitleFormatterContext);\n  if (value === null) {\n    throw new ReactContextError('TitleFormatterProvider');\n  }\n  return value;\n}\n\n/**\n * Returns a function to format the page title\n */\nexport function useTitleFormatter(): TitleFormatter {\n  const formatter = useTitleFormatterContext();\n  const {siteConfig} = useDocusaurusContext();\n  const {title: siteTitle, titleDelimiter} = siteConfig;\n\n  // Unfortunately we can only call this hook here, not in the provider\n  // Route context can't be accessed in any provider applied above the router\n  const {plugin} = useRouteContext();\n\n  return {\n    format: (title: string) =>","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/facebook/docusaurus/blob/3f483e80e326cc646b54b83d564b3f0c4881b9a6/packages/docusaurus-theme-common/src/utils/titleFormatterUtils.tsx#L77-L113","documentation":"useTitleFormatter() reads TitleFormatterContext via useTitleFormatterContext; when the context value is null (no TitleFormatterProvider ancestor), it throws a ReactContextError. The hook name in the message is parsed from the call stack, so the same generic error reports whichever consuming hook (useTitleFormatter, useTitleFormatterContext) was invoked outside the provider.","triggerScenarios":"Call useTitleFormatter() in a component rendered above TitleFormatterProvider; customize the theme root layout and omit or reorder the provider; call the hook in a context that is not a route child (provider is applied within the router tree).","commonSituations":"Swizzle/customize ThemeRoot or Layout and drop TitleFormatterProvider; using the hook in a top-level provider that sits above where Docusaurus injects it; calling the formatter outside React render (it is a hook).","solutions":["Keep the default theme provider chain intact so TitleFormatterProvider wraps the router.","If you swizzle the root, re-add <TitleFormatterProvider formatter={...}> around your tree (use the default formatter from TitleFormatterFnDefault).","Only call useTitleFormatter() from components rendered within a routed page."],"exampleFix":"// before (custom root, provider removed)\nexport default function Root({children}) {\n  return <>{children}</>;\n}\n// after\nimport {TitleFormatterProvider, TitleFormatterFnDefault} from '@docusaurus/theme-common/internal';\nexport default function Root({children}) {\n  return (\n    <TitleFormatterProvider formatter={TitleFormatterFnDefault}>\n      {children}\n    </TitleFormatterProvider>\n  );\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not remove TitleFormatterProvider when swizzling the root/layout.","Only call useTitleFormatter() from components inside the routed page tree.","When customizing the formatter, replace the provider value rather than deleting the provider."],"tags":["react","context","theme","title"],"backgroundTag":null,"analyzedSha":"3f483e80e326cc646b54b83d564b3f0c4881b9a6","analyzedAt":"2026-08-12T13:25:04.382Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}