{"record":{"id":"84da324d954fbc0b","repo":"shadcn-ui/ui","slug":"uselocks-must-be-used-within-locksprovider","errorCode":null,"errorMessage":"useLocks must be used within LocksProvider","messagePattern":"useLocks must be used within LocksProvider","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/v4/app/(app)/(create)/hooks/use-locks.tsx","lineNumber":56,"sourceCode":"      } else {\n        next.add(param)\n      }\n      return next\n    })\n  }, [])\n\n  const value = React.useMemo(\n    () => ({ locks, isLocked, toggleLock }),\n    [locks, isLocked, toggleLock]\n  )\n\n  return <LocksContext value={value}>{children}</LocksContext>\n}\n\nexport function useLocks() {\n  const context = React.useContext(LocksContext)\n  if (!context) {\n    throw new Error(\"useLocks must be used within LocksProvider\")\n  }\n  return context\n}\n","sourceCodeStart":38,"sourceCodeEnd":60,"githubUrl":"https://github.com/shadcn-ui/ui/blob/efac5987074af84ece57c367c6dd83387b967022/apps/v4/app/(app)/(create)/hooks/use-locks.tsx#L38-L60","documentation":"`useLocks` reads `LocksContext`, which `LocksProvider` populates via `useMemo(() => ({ locks, isLocked, toggleLock }), [...])`. A consumer mounted outside the provider gets undefined from `useContext` and throws — the lock API must never be partially absent while a panel checks `isLocked`.","triggerScenarios":"Calling `useLocks()` (e.g. `const { isLocked, toggleLock } = useLocks()`) in a component not under `<LocksProvider>`. Common when a panel that respects locks is rendered in isolation or hoisted above the provider.","commonSituations":"Splitting the create surface into separately mounted panes; rendering a lock-aware component inside a portal detached from the provider tree; tests that render the pane alone.","solutions":["Mount `<LocksProvider>` above every component that calls `useLocks()`.","Keep the provider at a stable point in the tree (near HistoryProvider) so lock state is shared across all panes.","In tests, decorate with the provider."],"exampleFix":"// before\n<LockablePanel />\n\n// after\n<LocksProvider>\n  <LockablePanel />\n</LocksProvider>","handlingStrategy":"type-guard","validationCode":"render(<LocksProvider>{<LockablePanel/>}</LocksProvider>)","typeGuard":"import React from \"react\"\nimport { LocksContext } from \"@/(app)/(create)/hooks/use-locks\"\nconst hasLocks = () => React.useContext(LocksContext) != null","tryCatchPattern":"try { useLocks() } catch (e) { if (e.message.includes(\"LocksProvider\")) {/*remount provider*/} throw e }","preventionTips":["Mount LocksProvider alongside the other (create) providers at the layout root.","Keep lock-aware panes inside the provider subtree.","Add the provider to test decorators."],"tags":["react","context","hooks","shadcn-v4","locks"],"backgroundTag":null,"analyzedSha":"efac5987074af84ece57c367c6dd83387b967022","analyzedAt":"2026-08-12T05:00:50.218Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}