{"record":{"id":"112998e1e9ad8d8b","repo":"mui/material-ui","slug":"no-tabcontext-provided","errorCode":null,"errorMessage":"No TabContext provided","messagePattern":"No TabContext provided","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/mui-lab/src/TabList/TabList.js","lineNumber":11,"sourceCode":"'use client';\nimport * as React from 'react';\nimport PropTypes from 'prop-types';\nimport Tabs from '@mui/material/Tabs';\nimport { useTabContext, getTabId, getPanelId } from '../TabContext';\n\nconst TabList = React.forwardRef(function TabList(props, ref) {\n  const { children: childrenProp, ...other } = props;\n  const context = useTabContext();\n  if (context === null) {\n    throw new TypeError('No TabContext provided');\n  }\n  const children = React.Children.map(childrenProp, (child) => {\n    if (!React.isValidElement(child)) {\n      return null;\n    }\n\n    return React.cloneElement(child, {\n      // SOMEDAY: `Tabs` will set those themselves\n      'aria-controls': getPanelId(context, child.props.value),\n      id: getTabId(context, child.props.value),\n    });\n  });\n\n  return (\n    <Tabs {...other} ref={ref} value={context.value}>\n      {children}\n    </Tabs>\n  );","sourceCodeStart":1,"sourceCodeEnd":29,"githubUrl":"https://github.com/mui/material-ui/blob/bdc96df2cb530fcdd60a7a7aabe37f610ce0f0a5/packages/mui-lab/src/TabList/TabList.js#L1-L29","documentation":"TabList from @mui/lab reads shared tab state via useTabContext(); the context returns null (not undefined) when no <TabContext> ancestor is present, and TabList throws a TypeError immediately because it needs context.value to wire aria-controls/ids on its Tab children. It is a hard precondition — TabList cannot render without the context.","triggerScenarios":"Rendering <TabList> directly without wrapping it in a <TabContext value={value}>. Common when copy-pasting only the TabList/Tab/TabPanel pieces from a lab tabs example, or when refactoring and accidentally removing the TabContext wrapper.","commonSituations":"Migrating from @mui/material Tabs to the @mui/lab TabContext/TabList/TabPanel composable API and forgetting the context; conditional rendering that mounts TabList in a branch where TabContext was not rendered.","solutions":["Wrap <TabList> (and its sibling <TabPanel>s) in <TabContext value={value}> so useTabContext returns the context object.","Ensure the same value state is shared by TabContext, TabList, and TabPanel.","If you do not need the composable API, switch to @mui/material <Tabs> which manages its own state."],"exampleFix":"// before\n<TabList onChange={handleChange}>\n  <Tab label=\"One\" value=\"1\" />\n</TabList>\n// after\n<TabContext value={value}>\n  <TabList onChange={handleChange}>\n    <Tab label=\"One\" value=\"1\" />\n  </TabList>\n</TabContext>","handlingStrategy":"validation","validationCode":"// Ensure a TabContext ancestor exists before mounting TabList.\nimport { useContext } from 'react';\nimport { TabContext } from '@mui/lab';\nfunction useHasTabContext() {\n  return useContext(TabContext) !== null;\n}","typeGuard":"import { Context as TabContextReactContext } from '@mui/lab/TabContext'; // pseudo\n// In practice, treat presence of <TabContext> in the JSX tree as the guard:\nfunction isInsideTabContext(): boolean { /* use useContext(TabContext) */ return true; }","tryCatchPattern":null,"preventionTips":["Always render TabList and TabPanel as descendants of <TabContext value={value}>.","Co-locate TabContext/TabList/TabPanel in the same component file when starting, to avoid accidentally separating them.","Add an ESLint rule or code review check that flags @mui/lab TabList/TabPanel imports without a TabContext import."],"tags":["react","lab","tabs","context","misuse"],"backgroundTag":null,"analyzedSha":"bdc96df2cb530fcdd60a7a7aabe37f610ce0f0a5","analyzedAt":"2026-08-12T22:59:56.717Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}