shadcn-ui/ui · error · Error

useHistory must be used within HistoryProvider

Error message

useHistory must be used within HistoryProvider

What it means

`useHistory` reads `HistoryContext`; the provider is `HistoryProvider`, which also mounts a `<PresetSync>` Suspense boundary. Calling `useHistory()` where `React.useContext(HistoryContext)` returns undefined throws — guaranteeing consumers always see `{ ... }` (history stack, push/redo, etc.) rather than a silent undefined.

Source

Thrown at apps/v4/app/(app)/(create)/hooks/use-history.tsx:182

  const value = React.useMemo(
    () => ({ canGoBack, canGoForward, goBack, goForward }),
    [canGoBack, canGoForward, goBack, goForward]
  )

  return (
    <HistoryContext value={value}>
      <Suspense>
        <PresetSync onPresetChange={onPresetChange} />
      </Suspense>
      {children}
    </HistoryContext>
  )
}

export function useHistory() {
  const context = React.useContext(HistoryContext)
  if (!context) {
    throw new Error("useHistory must be used within HistoryProvider")
  }
  return context
}

View on GitHub (pinned to efac598707)

Solutions

  1. Ensure every component calling `useHistory()` is a descendant of `<HistoryProvider>`.
  2. Re-add `<HistoryProvider onPresetChange={...}>{children}</HistoryProvider>` at the (create) layout root if it was removed.
  3. In tests, wrap the render in the provider (and a Suspense boundary, since PresetSync is mounted inside it).

Example fix

// before
const { history } = useHistory()

// after
<HistoryProvider onPresetChange={handlePreset}>
  <ComponentThatUsesHistory />
</HistoryProvider>
Defensive patterns

Strategy: type-guard

Validate before calling

// Wrap any isolated render of a history consumer:
render(<HistoryProvider onPresetChange={() => {}}>{<Consumer/>}</HistoryProvider>)

Type guard

import React from "react"
import { HistoryContext } from "@/(app)/(create)/hooks/use-history"
const hasHistory = () => React.useContext(HistoryContext) != null

Try / catch

try {
  useHistory()
} catch (e) {
  if (e.message.includes("HistoryProvider")) { /* mount provider or fallback */ }
  throw e
}

Prevention

When it happens

Trigger: Using `useHistory()` in a component rendered outside `<HistoryProvider>`, or before the provider has mounted in the (create) subtree. Also when a lazy-loaded component under Suspense resolves after the provider was removed from the tree.

Common situations: Refactoring the create-app layout and dropping the provider; adding a child route whose page uses history but whose parent layout no longer wraps with HistoryProvider; integration tests rendering a single panel.

Related errors


AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12). Data as JSON: /api/errors/c7e9664453402175. Report an issue: GitHub.