Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docusaurus build fails with "No Docusaurus route context found" for manually created sidebar with many items #10718

Closed
5 of 7 tasks
DonaldKellett opened this issue Nov 23, 2024 · 8 comments · Fixed by #10727
Closed
5 of 7 tasks
Labels
bug An error in the Docusaurus core causing instability or issues with its execution

Comments

@DonaldKellett
Copy link

Have you read the Contributing Guidelines on issues?

Prerequisites

  • I'm using the latest version of Docusaurus.
  • I have tried the npm run clear or yarn clear command.
  • I have tried rm -rf node_modules yarn.lock package-lock.json and re-installing packages.
  • I have tried creating a repro with https://new.docusaurus.io.
  • I have read the console error message carefully (if applicable).

Description

This is a duplicate of #10709 which was closed due to lacking a reproducible example. So here's a reproducible example: https://github.com/DonaldKellett/docusaurus-10709-repro

Building our production Technical KB written in Docusaurus with npm run build recently failed consistently with the error message below.

[cause]: Error: Unexpected: no Docusaurus route context found

The problem is reproducible in that the error appears 100% of the time when we try to add just 1 more item to our manually created sidebar (maybe our sidebar is too large?) regardless of what the item is or where it is placed within the sidebar, but our Docusaurus site contains sensitive and confidential information so we can't share the source code here. Nevertheless, we'll try to include as much relevant information as possible to help reproduce the issue without divulging too many details.

Reproducible demo

https://github.com/DonaldKellett/docusaurus-10709-repro

Steps to reproduce

Without divulging too many details, we're using Docusaurus v3.6.1 with the @docusaurus/faster plugin enabled though we found that the issue persists regardless of whether the experimental plugin is enabled or disabled.

Our package.json and package-lock.json files are as attached. In particular, the version of p-map used as seen in package-lock.json is 4.0.0 which is important as we will see later:

The issue is consistently triggered when we try to add 1 more item anywhere within our manually created sidebar in sidebars.js. Here's an overview of what it looks like:

/**
 * Creating a sidebar enables you to:
 - create an ordered group of docs
 - render a sidebar for each doc of that group
 - provide next/previous navigation

 The sidebars can be generated from the filesystem, or explicitly defined here.

 Create as many sidebars as you want.
 */

// @ts-check

/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
const sidebars = {
  // By default, Docusaurus generates a sidebar from the docs folder structure
  // tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],

  // But you can create a sidebar manually
  docs: [
    {
      type: "category",
      label: "GitLab",
      link: {
        type: "generated-index",
        title: "GitLab",
        description: "Articles related to GitLab",
      },
      items: [
        {
          type: "category",
          label: "Administrator Guide",
          link: {
            type: "generated-index",
            title: "Administrator Guide",
            description: "Administrator Guide for GitLab Helm Chart",
          },
          items: [
            "gitlab/install-gitlab-with-helm",
            "gitlab/enable-git-over-ssh-for-gitlab",
            "gitlab/enable-ad-login-for-gitlab",
            "gitlab/gitlab-properly-signed-tls",
            "gitlab/enable-gitlab-managed-terraform-backend",
            "gitlab/provide-custom-ca-gitlab-ci-jobs",
            "gitlab/cron-backup-gitlab-ee-16.x",
            "gitlab/gitlab-runner-https-certificate-error",
          ],
        },
        ...
      ]
    },
    ...
  ]
};

module.exports = sidebars;

For reference, here's what our docusaurus.config.js looks like (portions omitted due to containing sensitive information):

// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion

const lightCodeTheme = require("prism-react-renderer").themes.github;
const darkCodeTheme = require("prism-react-renderer").themes.dracula;

/** @type {import('@docusaurus/types').Config} */
const config = {
  future: {
    experimental_faster: true,
  },
  title: "Technical KB",
  tagline: "Internal technical knowledge base for Enfinity",
  favicon: "img/favicon.ico",

  // Set the production url of your site here
  url: "https://enfinity-solutions.pages.internal.enfinity.com.hk/",
  // Set the /<baseUrl>/ pathname under which your site is served
  // For GitHub pages deployment, it is often '/<projectName>/'
  baseUrl: "/internal/technical-kb/",

  // GitHub pages deployment config.
  // If you aren't using GitHub pages, you don't need these.
  organizationName: "facebook", // Usually your GitHub org/user name.
  projectName: "docusaurus", // Usually your repo name.

  onBrokenLinks: "throw",
  onBrokenMarkdownLinks: "warn",

  // Even if you don't use internalization, you can use this field to set useful
  // metadata like html lang. For example, if your site is Chinese, you may want
  // to replace "en" with "zh-Hans".
  i18n: {
    defaultLocale: "en",
    locales: ["en"],
  },

  presets: [
    [
      "classic",
      /** @type {import('@docusaurus/preset-classic').Options} */
      ({
        docs: {
          sidebarPath: require.resolve("./sidebars.js"),
          editUrl:
            "https://gitlab.internal.enfinity.com.hk/enfinity-solutions/internal/technical-kb/-/tree/main/",
        },
        blog: false,
        theme: {
          customCss: require.resolve("./src/css/custom.css"),
        },
      }),
    ],
  ],

  themeConfig:
    /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
    ({
      // Replace with your project's social card
      image: "img/docusaurus-social-card.jpg",
      navbar: {
        title: "Technical KB",
        logo: {
          alt: "My Site Logo",
          src: "img/logo.svg",
        },
        items: [
          { to: "/docs/category/gitlab", label: "GitLab", position: "left" },
          { to: "/docs/category/cloud", label: "Cloud", position: "left" },
          ...,
          {
            href: "https://gitlab.internal.enfinity.com.hk/enfinity-solutions/internal/technical-kb",
            label: "GitLab",
            position: "right",
          },
        ],
      },
      footer: {
        style: "dark",
        links: [
          {
            title: "Docs",
            items: [
              {
                label: "GitLab",
                to: "/docs/category/gitlab",
              },
              {
                label: "Cloud",
                to: "/docs/category/cloud",
              },
              ...
            ],
          },
          {
            title: "More",
            items: [
              {
                label: "GitLab",
                href: "https://gitlab.internal.enfinity.com.hk/enfinity-solutions/internal/technical-kb",
              },
            ],
          },
        ],
        copyright: `Copyright © ${new Date().getFullYear()} Enfinity Solutions Limited. Built with Docusaurus.`,
      },
      prism: {
        theme: lightCodeTheme,
        darkTheme: darkCodeTheme,
      },
    }),
};

module.exports = config;

Expected behavior

Building the site with npm run build finishes without issues. The site loads and displays correctly with npm run serve.

Actual behavior

Docusaurus static site generation failed for 306 paths:

> [email protected] build
> docusaurus build
[INFO] [en] Creating an optimized production build...
[ERROR] Error: Unable to build website for locale en.
    at tryToBuildLocale (/builds/enfinity-solutions/internal/technical-kb/node_modules/@docusaurus/core/lib/commands/build/build.js:78:15)
    at async /builds/enfinity-solutions/internal/technical-kb/node_modules/@docusaurus/core/lib/commands/build/build.js:34:9
    at async mapAsyncSequential (/builds/enfinity-solutions/internal/technical-kb/node_modules/@docusaurus/utils/lib/jsUtils.js:21:24)
    at async Command.build (/builds/enfinity-solutions/internal/technical-kb/node_modules/@docusaurus/core/lib/commands/build/build.js:33:5) {
  [cause]: Error: Docusaurus static site generation failed for 306 paths:
...

The detailed error for each failure is "Error: Unexpected: no Docusaurus route context found" which can be traced down to p-map/index.js:57:22 and is identical for each failure.

Error: Can't render static file for pathname "/internal/technical-kb/docs/aiml/install-pyenv"
            at generateStaticFile (/builds/enfinity-solutions/internal/technical-kb/node_modules/@docusaurus/core/lib/ssg/ssg.js:167:15)
            at processTicksAndRejections (node:internal/process/task_queues:105:5)
            at runNextTicks (node:internal/process/task_queues:69:3)
            at process.processImmediate (node:internal/timers:459:9)
            at async /builds/enfinity-solutions/internal/technical-kb/node_modules/p-map/index.js:57:22 {
          [cause]: Error: Unexpected: no Docusaurus route context found
              at mergeContexts (server.bundle.js:10977:19)
              at server.bundle.js:10995:16
              at Object.Ic [as useMemo] (server.bundle.js:3227:240)
              at __webpack_modules__.72408.exports.useMemo (server.bundle.js:4808:208)
              at RouteContextProvider (server.bundle.js:10994:69)
              at Uc (server.bundle.js:3234:44)
              at Xc (server.bundle.js:3236:253)
              at Z (server.bundle.js:3242:89)
              at Vc (server.bundle.js:3234:473)
              at Xc (server.bundle.js:3236:210)
        },

The offending line in version 4.0.0 of p-map is: https://github.com/sindresorhus/p-map/blob/a4b4dec459544d98880bc53a580e53691aff9fa9/index.js#L57

result[index] = await mapper(element, index);

Screenshots containing the error messages in our failing GitLab CI builds are attached below.

2024-11-22 12_15_40-Window
2024-11-22 12_15_11-Window

Your environment

Self-service

  • I'd be willing to fix this bug myself.
@DonaldKellett DonaldKellett added bug An error in the Docusaurus core causing instability or issues with its execution status: needs triage This issue has not been triaged by maintainers labels Nov 23, 2024
DonaldKellett pushed a commit to DonaldKellett/docusaurus-10709-repro that referenced this issue Nov 23, 2024
@DonaldKellett
Copy link
Author

Here's the commit that triggers the bug causing the build to fail: DonaldKellett/docusaurus-10709-repro@2c4431b As can be seen from the commit, adding just a single item to the sidebar anywhere triggers this cryptic build error.

The failing job and build logs in CI: https://github.com/DonaldKellett/docusaurus-10709-repro/actions/runs/11983861175/job/33413927236

@DonaldKellett
Copy link
Author

Just discovered that the build error disappears when duplicate sub-category names are renamed to become unique, e.g. these 2:

  1. "Kubernetes > Storage": https://github.com/DonaldKellett/docusaurus-10709-repro/blob/main/sidebars.js#L233-L248
  2. "OpenShift > Storage": https://github.com/DonaldKellett/docusaurus-10709-repro/blob/main/sidebars.js#L488-L502

Nevertheless, I insist this is a bug in Docusaurus since the build process should catch duplicated sub-category names in the sidebar if it is not a supported use-case and exit with a human-readable error message instead of exhibiting unspecified behavior and randomly failing builds with a cryptic error message when a certain number of sidebar items is reached.

@slorber
Copy link
Collaborator

slorber commented Nov 25, 2024

Sorry for closing your initial issue too eagerly, I didn't know you planned to provide a runnable repro. We usually re-open the issue once a repro is provided.

Thanks for the repro, this definitively looks like a bug / DX problem.

I suspect both of your categories have the same final URL, and this leads to conflicts/ name collision later in JS modules emitted by Docusaurus.

I'll investigate at the end of the week.

Until then I'm curious, what is the pathname you access both of these generated index categories? I suspect it's the same pathname, something like:

/docs/category/storage

And you could use the slug attribute to see if it improves things:

        {
          type: "category",
          label: "Storage",
          link: {
            type: "generated-index",
            title: "Storage",
            description: "Articles related to storage on Kubernetes",
            slug: "my-kuternete-storage-slug",
          },
}

I'll still consider it a bug though, because we should prevent these collisions in the first place or at least fail-fast on this case and emit a clear actionable error message for the user.

@slorber slorber removed the status: needs triage This issue has not been triaged by maintainers label Nov 25, 2024
@comp615
Copy link

comp615 commented Nov 25, 2024

Again, maybe not helpful, but we are also experiencing a similar issue where 3.6+ versions are throwing lots of missing context errors in custom sidebars during prod compilation (I think dev works? And I think 3.6.3 was triggering it for us; or some pseudo randomness?). I have not debugged our setup or checked for collisions like mentioned above, but wanted to add that I think this is a more broad current pain point potentially.

@DonaldKellett
Copy link
Author

Sorry for closing your initial issue too eagerly, I didn't know you planned to provide a runnable repro. We usually re-open the issue once a repro is provided.

Thanks for the repro, this definitively looks like a bug / DX problem.

I suspect both of your categories have the same final URL, and this leads to conflicts/ name collision later in JS modules emitted by Docusaurus.

I'll investigate at the end of the week.

Until then I'm curious, what is the pathname you access both of these generated index categories? I suspect it's the same pathname, something like:

/docs/category/storage

And you could use the slug attribute to see if it improves things:

        {
          type: "category",
          label: "Storage",
          link: {
            type: "generated-index",
            title: "Storage",
            description: "Articles related to storage on Kubernetes",
            slug: "my-kuternete-storage-slug",
          },
}

I'll still consider it a bug though, because we should prevent these collisions in the first place or at least fail-fast on this case and emit a clear actionable error message for the user.

Thanks! I believe the generated pathname for both subcategories is indeed /docs/category/storage as you suggested.

While our team fixed the build by re-assigning unique names, e.g. "Kubernetes Storage" vs. "OpenShift Storage", may I ask what the optional slug field does in this context? Does it override the auto-generated category pathname, e.g. changing /docs/category/storage to /docs/category/my-kubernetes-storage-slug?

@slorber
Copy link
Collaborator

slorber commented Nov 25, 2024

slug permits to choose a custom pathname / url suffix for that category: https://docusaurus.io/docs/sidebar/items#generated-index-page


Again, maybe not helpful, but we are also experiencing a similar issue where 3.6+ versions are throwing lots of missing context errors in custom sidebars during prod compilation (I think dev works? And I think 3.6.3 was triggering it for us; or some pseudo randomness?). I have not debugged our setup or checked for collisions like mentioned above, but wanted to add that I think this is a more broad current pain point potentially.

The bug being reported here is likely a historical one, not related to a recent release.

I don't see any recent change that could lead to that kind of error in v3.6+ (apart from the opt-in Docusaurus Faster flags maybe). Please try to be sure. Because we can't do much with a vague comment like that 😅. We need runnable bug repros, a precise bug description, with exact version numbers that succeed or break your app.

It's possible that the bug feels "random" because it might be sensitive to the order in which Docusaurus emit modules, and Docusaurus runs code in parallel. Maybe your app still works if module A overrides module B, and only fails if module B overrides module A.

@slorber
Copy link
Collaborator

slorber commented Nov 29, 2024

Damn, this was not easy to troubleshoot. Many little things could "fix" the problem but it wasn't clear why, and what's the best fix for it.

This is really bad luck, you had 1/1000 chance for encountering a hash collision in our route chunks codename generation.

2 route definitions with the same path lead to the exact same hash:

CONFLICT /internal/technical-kb/docs-456 {
  plugin: { name: 'docusaurus-plugin-content-docs', id: 'default' },
  path: '/internal/technical-kb/docs',
  exact: false,
  component: '@theme/DocsRoot',
  routes: [
    {
      path: '/internal/technical-kb/docs',
      exact: false,
      component: '@theme/DocVersionRoot',
      routes: [Array],
      props: undefined,
      priority: -1,
      modules: [Object]
    }
  ],
  context: {
    plugin: '@generated/docusaurus-plugin-content-docs/default/__plugin.json'
  },
  modules: {},
  props: undefined
}

CONFLICT /internal/technical-kb/docs-456 {
  path: '/internal/technical-kb/docs',
  exact: false,
  component: '@theme/DocVersionRoot',
  routes: [
    {
      path: '/internal/technical-kb/docs',
      exact: false,
      component: '@theme/DocRoot',
      routes: [Array],
      modules: {},
      props: undefined
    }
  ],
  props: undefined,
  priority: -1,
  modules: {
    __props: '@generated/docusaurus-plugin-content-docs/default/p/internal-technical-kb-docs-462.json'
  }
}

This leads routeChunkNames to look like this:

/internal/technical-kb/docs-456
{__comp: '__comp---theme-doc-version-roota-7-b-5de', __props: '__props---internal-technical-kb-docsce-3-cb8'}

/internal/technical-kb/docs-994
{__comp: '__comp---theme-doc-roota-94-67a'}

Instead of this:

/internal/technical-kb/docs-8a8
{__comp: '__comp---theme-doc-version-roota-7-b-5de', __props: '__props---internal-technical-kb-docs-661-be4'}

/internal/technical-kb/docs-331
{__comp: '__comp---theme-doc-roota-94-67a'}

/internal/technical-kb/docs-431
{__comp: '__comp---theme-docs-root-5-e-9-0b6', __context: {plugin: 'plugin---internal-technical-kb-docsaba-b8a'}}

Note that 2 routes with the same path are normal/expected, it's how we handle the docs routing tree:

{
 path: "/docs",
 component: "@theme/DocsRoot",
 routes: [
   {
     path: "/docs",
     component: "@theme/DocVersionRoot"
     routes: []
   }  
 ]
}

Here what happens in practice is that the parent route has the exact same hash as its child 😅 and this leads to a hash collision because we generate unique keys using ${route.path}-${hash(route)}

@slorber
Copy link
Collaborator

slorber commented Nov 29, 2024

Will be fixed in the next release with #10727

Note that in your case, the issue is only temporary. Editing many things on your site will trigger new hashes to be computed, and the collision will not be there anymore. Just editing any sidebar item or category label fixes the collision for example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug An error in the Docusaurus core causing instability or issues with its execution
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants