{"record":{"id":"6ab48b93588a1b80","repo":"shadcn-ui/ui","slug":"usecarousel-must-be-used-within-a-carousel","errorCode":null,"errorMessage":"useCarousel must be used within a <Carousel />","messagePattern":"useCarousel must be used within a <Carousel />","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/v4/registry/bases/aria/ui/carousel.tsx","lineNumber":39,"sourceCode":"  setApi?: (api: CarouselApi) => void\n}\n\ntype CarouselContextProps = {\n  carouselRef: ReturnType<typeof useEmblaCarousel>[0]\n  api: ReturnType<typeof useEmblaCarousel>[1]\n  scrollPrev: () => void\n  scrollNext: () => void\n  canScrollPrev: boolean\n  canScrollNext: boolean\n} & CarouselProps\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null)\n\nfunction useCarousel() {\n  const context = React.useContext(CarouselContext)\n\n  if (!context) {\n    throw new Error(\"useCarousel must be used within a <Carousel />\")\n  }\n\n  return context\n}\n\nfunction Carousel({\n  orientation = \"horizontal\",\n  opts,\n  setApi,\n  plugins,\n  className,\n  children,\n  ...props\n}: React.ComponentProps<\"div\"> & CarouselProps) {\n  const [carouselRef, api] = useEmblaCarousel(\n    {\n      ...opts,\n      axis: orientation === \"horizontal\" ? \"x\" : \"y\",","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/shadcn-ui/ui/blob/efac5987074af84ece57c367c6dd83387b967022/apps/v4/registry/bases/aria/ui/carousel.tsx#L21-L57","documentation":"`useCarousel` reads `CarouselContext` (`createContext<CarouselContextProps | null>(null)`); `<Carousel>` (embla-based) provides orientation, api, scrollPrev/Next, canScroll*. Any carousel sub-part (CarouselPrevious/Next/Items/Item) rendered outside `<Carousel>` throws so the embla api is never null at a consumer.","triggerScenarios":"Using `<CarouselNext />` / `<CarouselPrevious />` / `<CarouselItems />` / `<CarouselItem />` as a sibling of (or above) `<Carousel>` rather than as a descendant. Also when wrapping Carousel's children in a fragment-level portal that detaches from the context tree.","commonSituations":"Copying Carousel markup from docs and placing the buttons outside the Carousel root; composing a custom carousel layout that lifts buttons out; tests rendering a single part.","solutions":["Make every Carousel sub-component a DOM/logical descendant of `<Carousel>`.","Keep `<CarouselPrevious />` / `<CarouselNext />` inside the `<Carousel>` subtree even if visually positioned outside via CSS.","Decorate tests/stories with `<Carousel>`."],"exampleFix":"// before\n<Carousel />\n<CarouselPrevious />\n\n// after\n<Carousel>\n  <CarouselItems>\n    <CarouselItem>...</CarouselItem>\n  </CarouselItems>\n  <CarouselPrevious />\n  <CarouselNext />\n</Carousel>","handlingStrategy":"type-guard","validationCode":"render(<Carousel><CarouselItems><CarouselItem>x</CarouselItem></CarouselItems><CarouselPrevious/><CarouselNext/></Carousel>)","typeGuard":"import React from \"react\"\nimport { CarouselContext } from \"@/registry/bases/aria/ui/carousel\"\nconst insideCarousel = () => React.useContext(CarouselContext) != null","tryCatchPattern":"try { useCarousel() } catch (e) { if (e.message.includes(\"<Carousel />\")) {/*nest inside Carousel*/} throw e }","preventionTips":["Always nest Carousel sub-parts under <Carousel>.","Keep CarouselPrevious/Next inside the tree even when CSS-positioned outside.","Add <Carousel> to story/test decorators for carousel parts."],"tags":["react","context","hooks","shadcn","carousel","aria-style"],"backgroundTag":null,"analyzedSha":"efac5987074af84ece57c367c6dd83387b967022","analyzedAt":"2026-08-12T05:00:50.218Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}