facebook/docusaurus · error · Error

Can't create navigation link: no doc found with id=${docId}

Error message

Can't create navigation link: no doc found with id=${docId}

What it means

Thrown by getDocById() inside toNavigationLink(). When converting a SidebarNavigationItem (a doc or a doc-linked category) into a PropNavigationLink for theme rendering, the plugin looks the doc id up in docsById. If the id is absent the build aborts because navigation data would otherwise point at a non-existent page.

Source

Thrown at packages/docusaurus-plugin-content-docs/src/sidebars/utils.ts:507

      pagination_label: paginationLabel,
      sidebar_label: sidebarLabel,
    },
  } = doc;
  return {
    title:
      paginationLabel ?? sidebarLabel ?? options?.sidebarItemLabel ?? title,
    permalink,
  };
}

export function toNavigationLink(
  navigationItem: SidebarNavigationItem | undefined,
  docsById: {[docId: string]: DocMetadataBase},
): PropNavigationLink | undefined {
  function getDocById(docId: string) {
    const doc = docsById[docId];
    if (!doc) {
      throw new Error(
        `Can't create navigation link: no doc found with id=${docId}`,
      );
    }
    return doc;
  }

  if (!navigationItem) {
    return undefined;
  }

  if (navigationItem.type === 'category') {
    return navigationItem.link.type === 'doc'
      ? toDocNavigationLink(getDocById(navigationItem.link.id))
      : {
          title: navigationItem.label,
          permalink: navigationItem.link.permalink,
        };
  }

View on GitHub (pinned to 3f483e80e3)

Solutions

  1. Run `docusaurus clear` to wipe stale caches, then rebuild - the inconsistency is often caused by cached metadata.
  2. If you use a custom SidebarItemsGenerator, ensure every returned doc id exists in the docs array passed to it.
  3. Verify no doc referenced in sidebars has draft:true (drafts are excluded from docsById for navigation).
  4. Check versioned sidebars align with versioned docs (no dangling ids).
Defensive patterns

Strategy: validation

Validate before calling

// If you build navigation programmatically, guard against missing docs.
function safeToNavigationLink(navItem, docsById) {
  if (!navItem) return undefined;
  if (navItem.type === 'category' && navItem.link?.type === 'doc') {
    if (!docsById[navItem.link.id]) return undefined; // skip instead of throw
  }
  if (navItem.type === 'doc' && !docsById[navItem.id]) return undefined;
  return navItem;
}

Type guard

function navItemHasExistingDoc(navItem, docsById) {
  if (navItem.type === 'doc') return Boolean(docsById[navItem.id]);
  if (navItem.type === 'category' && navItem.link?.type === 'doc') {
    return Boolean(docsById[navItem.link.id]);
  }
  return true;
}

Prevention

When it happens

Trigger: A sidebar navigation item references a doc id that was filtered out (e.g. draft), renamed, or deleted between sidebar collection and navigation rendering; an inconsistency where sidebarNameToDocIds contains an id but docsById does not (plugin-internal state divergence); versioned navigation computed against the wrong version's docs.

Common situations: Race between draft filtering and navigation generation; manual mutation of sidebar structures via a custom generator returning ids not present in the docs array; bugs from custom plugins that inject nav items; partial cache (clear with `docusaurus clear`).

Related errors


AI-assisted analysis of facebook/docusaurus@3f483e80e3 (2026-08-12). Data as JSON: /api/errors/842e01eb9605c5a7. Report an issue: GitHub.