{"record":{"id":"263f15c11fa207a1","repo":"janhq/jan","slug":"chainofthought-components-must-be-used-within-chainofthought","errorCode":null,"errorMessage":"ChainOfThought components must be used within ChainOfThought","messagePattern":"ChainOfThought components must be used within ChainOfThought","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web-app/src/components/ai-elements/chain-of-thought.tsx","lineNumber":57,"sourceCode":"// ── Context ────────────────────────────────────────────────────────────────\n\ntype ChainOfThoughtContextValue = {\n  isOpen: boolean\n  setIsOpen: (open: boolean) => void\n  isStreaming: boolean\n  duration: number | undefined\n}\n\nconst MS_IN_S = 1000\n\nconst ChainOfThoughtContext = createContext<ChainOfThoughtContextValue | null>(\n  null\n)\n\nexport const useChainOfThought = () => {\n  const context = useContext(ChainOfThoughtContext)\n  if (!context) {\n    throw new Error(\n      'ChainOfThought components must be used within ChainOfThought'\n    )\n  }\n  return context\n}\n\n// ── ChainOfThought (root) ──────────────────────────────────────────────────\n\nexport type ChainOfThoughtProps = ComponentProps<typeof Collapsible> & {\n  isStreaming?: boolean\n  /** When true the collapsible auto-collapses (e.g. text content appeared after this CoT group). */\n  shouldCollapse?: boolean\n  /** When true the collapsible is forced open and overrides auto-collapse (e.g. a tool is awaiting approval). */\n  forceOpen?: boolean\n  open?: boolean\n  defaultOpen?: boolean\n  onOpenChange?: (open: boolean) => void\n  /** Persisted trace duration (ms), used to seed the header when a restored","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/janhq/jan/blob/7205d770c1e097c3daf35a911176410e93bc5564/web-app/src/components/ai-elements/chain-of-thought.tsx#L39-L75","documentation":"useChainOfThought is a React context hook that reads ChainOfThoughtContext, which is only populated by the ChainOfThought provider component. If the context value is null (hook called outside a <ChainOfThought> wrapper), the hook throws this Error to fail fast.","triggerScenarios":"Calling useChainOfThought (or rendering a subcomponent like ChainOfThoughtItem that internally calls it) outside of a <ChainOfThought> ancestor — e.g. rendering thought items at the top level of a page.","commonSituations":"Refactoring moved a child component out of the ChainOfThought wrapper; conditional rendering mounts the child without the parent; storybook/test renders the hook's consumer standalone.","solutions":["Wrap the consuming component in <ChainOfThought> ... </ChainOfThought>","Move any component calling useChainOfThought inside the provider's children","If the hook may run outside, guard with a nullable-context variant instead of the throwing one","Check JSX ordering — the provider must be an ancestor, not a sibling"],"exampleFix":"// before\n<ChainOfThoughtItem step={step} /> // thrown: no context\n// after\n<ChainOfThought isStreaming={isStreaming}>\n  <ChainOfThoughtItem step={step} />\n</ChainOfThought>","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function useChainOfThoughtSafe() {\n  return useContext(ChainOfThoughtContext); // returns null outside provider\n}\n// consumer:\nconst ctx = useChainOfThoughtSafe();\nif (ctx === null) throw new Error('ChainOfThought components must be used within ChainOfThought');","tryCatchPattern":"try {\n  render(<ChainOfThoughtItem step={step} />);\n} catch (e) {\n  if (e.message.includes('must be used within ChainOfThought')) {\n    console.error('JSX error: wrap the component in <ChainOfThought>');\n  }\n}","preventionTips":["Always render subcomponents as children of <ChainOfThought>","Add an ESLint/React rule or unit test that asserts the provider wraps consumers","After refactors, re-check JSX ancestry of context-consuming components","Keep hooks and their provider components in the same module to make the contract obvious"],"tags":["react","context","typescript","hook"],"backgroundTag":"missing-required-context-provider","analyzedSha":"7205d770c1e097c3daf35a911176410e93bc5564","analyzedAt":"2026-09-17T14:27:30.100Z","contentChangedAt":"2026-09-17T14:27:30.100Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}