Skip to content

bug(site): docs pages crash with "CodeBlock is not defined" (both dev and production build) #7578

Description

@JSONbored

Summary

Every docs page that uses the <CodeBlock> MDX component (most of content/docs/*.mdx, e.g. quickstart.mdx) fails to render, showing the generic "This page didn't load" error boundary instead of content. Confirmed on /docs/quickstart, reproducible in both vite dev and a production vite build + vite preview, in a completely fresh browser tab (rules out HMR/module-cache staleness).

Root symptom

Browser console:

Error: CodeBlock is not defined
    at http://localhost:8080/docs/quickstart:...

This is a raw ReferenceError, not fumadocs' own friendly _missingMdxReference message ("Expected component CodeBlock to be defined..."), which means the compiled MDX module's const {Callout, CodeBlock} = _components destructuring line is not actually running before the <CodeBlock> JSX usage sites evaluate -- or _components genuinely lacks CodeBlock at runtime despite the source wiring looking correct.

What I ruled out

  • Not a Vite dep-cache issue: cleared node_modules/.vite and the generated .source/ fumadocs output, restarted the dev server fresh -- still reproduces.
  • Not browser-tab/HMR state: reproduces in a brand-new tab on first navigation.
  • Not dev-only: reproduces identically on a vite build + vite preview production bundle.
  • Not a missing import: docsMdxComponents (src/lib/docs-mdx-components.tsx) correctly imports and maps CodeBlock from src/components/site/primitives.tsx, which is a plain top-level export function CodeBlock(...) with no circular-import risk (only imports lucide-react, react, sonner, @/lib/utils).
  • The compiled MDX output looks structurally correct when fetched directly (curl 'http://localhost:8080/content/docs/quickstart.mdx?collection=docs'): _createMdxContent(props) does const _components = {...defaults, ...props.components}, {Callout, CodeBlock} = _components; and later references the destructured CodeBlock identifier consistently across all 4 usage sites in the file -- this is standard, valid MDX-compiler output shape.
  • The prop-passing chain looks correct on paper: docs.quickstart.tsx's route component calls docsClientLoader.getComponent(path) then renders <Content /> (no props) -> fumadocs-mdx's Renderer(props) -> our custom component(doc, props) in src/lib/docs-client-loader.tsx, which ignores the passed-in props and unconditionally returns <MDXContent components={docsMdxComponents} /> -- so MDXContent's own props.components should always be docsMdxComponents, regardless of what <Content /> was called with.

Where I'd look next

Given static tracing of the whole chain (docs.quickstart.tsx -> docsClientLoader -> fumadocs-mdx/dist/runtime/browser.js's Renderer/use() -> compiled MDXContent/_createMdxContent) all looks correct, but the runtime behavior disagrees, I'd suspect either:

  • A genuine fumadocs-mdx/MDX-compiler version mismatch in how the components prop merges into the compiled module's scope (worth trying a fumadocs-mdx version bump or diffing its browser runtime against its own test fixtures).
  • Something about the use() + Suspense timing in Renderer causing _createMdxContent to execute in a stale/detached closure on a subsequent render pass.
  • Instrumenting component({default: MDXContent}, props) in docs-client-loader.tsx with a temporary console.log(props, docsMdxComponents) and reproducing live would settle this quickly -- I did not want to leave debug instrumentation in place without a clear fix.

Scope

Affects /docs/quickstart confirmed; likely affects most/all of the ~50 docs.*.tsx routes, since CodeBlock (and probably Callout, which has the identical destructuring pattern) is used broadly across content/docs/*.mdx.

Why filed separately

Found incidentally while manually verifying the UI for #7567 (unrelated fairness-analytics work) -- filing separately since it's a pre-existing, unrelated bug that deserves focused investigation rather than being bolted onto that PR.

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions