{"record":{"id":"f8c30a9295bac186","repo":"facebook/docusaurus","slug":"sidebar-category-item-label-has-neither-any-sub","errorCode":null,"errorMessage":"Sidebar category ${item.label} has neither any subitem nor a link. This makes this item not able to link to anything.","messagePattern":"Sidebar category (.+?) has neither any subitem nor a link\\. This makes this item not able to link to anything\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/docusaurus-plugin-content-docs/src/sidebars/postProcessor.ts","lineNumber":54,"sourceCode":"    const permalink = normalizeUrl([params.version.path, slug]);\n    return {\n      ...category.link,\n      slug,\n      permalink,\n    };\n  }\n  return category.link;\n}\n\nfunction postProcessSidebarItem(\n  item: ProcessedSidebarItem,\n  params: SidebarPostProcessorParams,\n): SidebarItem | null {\n  if (item.type === 'category') {\n    // Fail-fast if there's actually no subitems, no because all subitems are\n    // drafts. This is likely a configuration mistake.\n    if (item.items.length === 0 && !item.link) {\n      throw new Error(\n        `Sidebar category ${item.label} has neither any subitem nor a link. This makes this item not able to link to anything.`,\n      );\n    }\n    const category = {\n      ...item,\n      collapsed: item.collapsed ?? params.sidebarOptions.sidebarCollapsed,\n      collapsible: item.collapsible ?? params.sidebarOptions.sidebarCollapsible,\n      link: normalizeCategoryLink(item, params),\n      items: item.items\n        .map((subItem) => postProcessSidebarItem(subItem, params))\n        .filter((v): v is SidebarItem => Boolean(v)),\n    };\n\n    // If the current category doesn't have subitems, we render a normal link\n    // instead.\n    if (category.items.length === 0) {\n      // Doesn't make sense to render an empty generated index page, so we\n      // filter the entire category out as well.","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/facebook/docusaurus/blob/3f483e80e326cc646b54b83d564b3f0c4881b9a6/packages/docusaurus-plugin-content-docs/src/sidebars/postProcessor.ts#L36-L72","documentation":"Thrown by postProcessSidebarItem() during the sidebar post-processing pass. A category item that has zero children AND no link cannot navigate to anything, so Docusaurus treats it as a configuration mistake and aborts. The check is intentionally fail-fast (commented 'not because all subitems are drafts') so authors notice empty categories immediately rather than shipping dead nav nodes.","triggerScenarios":"Declaring a category in sidebars.js with an empty items array and no link property; a category whose only children are all draft docs (filtered out before this check runs); an autogenerated category whose directory contains only draft or unlisted files; removing the last child of a category during refactoring without giving the category a link.","commonSituations":"Adding a placeholder category intending to fill it later; setting draft: true on every doc inside a folder that backs a category; deleting the last doc in a category; converting all child docs to ref items that get filtered out; migration where a category lost its children but kept its label.","solutions":["Give the category a link so it resolves to a page: {type:'category', label:'X', link:{type:'doc', id:'x/index'}, items:[]}.","Add at least one non-draft child doc to the category's items (or to the backing directory for autogenerated categories).","Remove the empty category from the sidebar entirely if it is no longer needed.","If children are drafts you actually want published, set draft:false on at least one of them."],"exampleFix":"// before: category with no children and no link\nconst sidebars = {\n  guide: [{type: 'category', label: 'Empty', items: []}],\n};\n\n// after: give it a generated-index link\nconst sidebars = {\n  guide: [{\n    type: 'category',\n    label: 'Empty',\n    link: {type: 'generated-index'},\n    items: [],\n  }],\n};","handlingStrategy":"validation","validationCode":"// Walk the sidebar tree and flag categories that would trigger the error.\nfunction findEmptyLinklessCategories(items, acc = []) {\n  for (const item of items) {\n    if (item.type === 'category') {\n      if ((!item.items || item.items.length === 0) && !item.link) {\n        acc.push(item.label);\n      }\n      if (item.items) findEmptyLinklessCategories(item.items, acc);\n    }\n  }\n  return acc;\n}\nconst bad = findEmptyLinklessCategories(sidebars.tutorial);\nif (bad.length) throw new Error('Empty linkless categories: ' + bad.join(', '));","typeGuard":"function categoryHasTarget(cat) {\n  return (Array.isArray(cat.items) && cat.items.length > 0) || Boolean(cat.link);\n}","tryCatchPattern":null,"preventionTips":["Never declare a category without at least one child or a link.","When converting docs to drafts, check parent categories still resolve.","For autogenerated folders, ensure each _category_ folder holds at least one published doc."],"tags":["docs","sidebar","category","configuration"],"backgroundTag":null,"analyzedSha":"3f483e80e326cc646b54b83d564b3f0c4881b9a6","analyzedAt":"2026-08-12T13:25:04.382Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}