shadcn-ui/ui · error · Error

useCarousel must be used within a <Carousel />

Error message

useCarousel must be used within a <Carousel />

What it means

Identical contract to [151] but in the `base` style registry. `useCarousel` reads `CarouselContext`; carousel sub-parts rendered outside `<Carousel>` throw so the embla api is never null.

Source

Thrown at apps/v4/registry/bases/base/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. Nest all Carousel sub-components under `<Carousel>` from the `base` style import path.
  2. Keep buttons inside the Carousel subtree even when CSS-positioned elsewhere.
  3. Decorate tests/stories with `<Carousel>`.

Example fix

// before
<Carousel />
<CarouselNext />

// 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>) // base style imports

Type guard

import React from "react"
import { CarouselContext } from "@/registry/bases/base/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: Mounting `<CarouselPrevious />` / `<CarouselNext />` / `<CarouselItem />` outside `<Carousel>` when importing from the `base` style. Same shape as the aria variant.

Common situations: Using the `base` (non-aria) style and copying markup that places buttons outside Carousel; composing a custom layout; tests of individual parts.

Related errors


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