shadcn-ui/ui · error · Error

useCarousel must be used within a <Carousel />

Error message

useCarousel must be used within a <Carousel />

What it means

`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.

Source

Thrown at apps/v4/registry/bases/aria/ui/carousel.tsx:39

  setApi?: (api: CarouselApi) => void
}

type CarouselContextProps = {
  carouselRef: ReturnType<typeof useEmblaCarousel>[0]
  api: ReturnType<typeof useEmblaCarousel>[1]
  scrollPrev: () => void
  scrollNext: () => void
  canScrollPrev: boolean
  canScrollNext: boolean
} & CarouselProps

const CarouselContext = React.createContext<CarouselContextProps | null>(null)

function useCarousel() {
  const context = React.useContext(CarouselContext)

  if (!context) {
    throw new Error("useCarousel must be used within a <Carousel />")
  }

  return context
}

function Carousel({
  orientation = "horizontal",
  opts,
  setApi,
  plugins,
  className,
  children,
  ...props
}: React.ComponentProps<"div"> & CarouselProps) {
  const [carouselRef, api] = useEmblaCarousel(
    {
      ...opts,
      axis: orientation === "horizontal" ? "x" : "y",

View on GitHub (pinned to efac598707)

Solutions

  1. Make every Carousel sub-component a DOM/logical descendant of `<Carousel>`.
  2. Keep `<CarouselPrevious />` / `<CarouselNext />` inside the `<Carousel>` subtree even if visually positioned outside via CSS.
  3. Decorate tests/stories with `<Carousel>`.

Example fix

// before
<Carousel />
<CarouselPrevious />

// after
<Carousel>
  <CarouselItems>
    <CarouselItem>...</CarouselItem>
  </CarouselItems>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>
Defensive patterns

Strategy: type-guard

Validate before calling

render(<Carousel><CarouselItems><CarouselItem>x</CarouselItem></CarouselItems><CarouselPrevious/><CarouselNext/></Carousel>)

Type guard

import React from "react"
import { CarouselContext } from "@/registry/bases/aria/ui/carousel"
const insideCarousel = () => React.useContext(CarouselContext) != null

Try / catch

try { useCarousel() } catch (e) { if (e.message.includes("<Carousel />")) {/*nest inside Carousel*/} throw e }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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