Skip to content

[Bug]: addon-docs: MDX compilation fails with Vite — providerImportSource uses raw file:// URL instead of a resolvable path #34545

Description

@yannbf

Describe the bug

When a Storybook project includes .mdx story files, the Vite dev server throws:

Vite Internal server error: Failed to resolve import
"file:///path/to/node_modules/@storybook/addon-docs/dist/mdx-react-shim.js"
from "SomeFile.mdx". Does the file exist?
Plugin: vite:import-analysis
The MDX compiler emits an import using a file:// URL as the specifier:

import { useMDXComponents as _provideComponents } from
  "file:///absolute/path/to/node_modules/@storybook/addon-docs/dist/mdx-react-shim.js";
Vite's vite:import-analysis plugin cannot resolve file:// URL import specifiers, so the build fails.

Root cause

In addon-docs/dist/preset.js and addon-docs/dist/_node-chunks/mdx-plugin-5AO2VUFZ.js, providerImportSource is set using a raw import.meta.resolve() call:

// ✗ raw file:// URL — Vite cannot resolve this as an import specifier
providerImportSource: import.meta.resolve("@storybook/addon-docs/mdx-react-shim"),

import.meta.resolve() in Node.js ESM always returns a file:// URL. This is used verbatim by the MDX compiler as the import source in the compiled output.

Notably, @mdx-js/react is handled correctly in the same file:

// ✓ fileURLToPath converts file:// → absolute path, added as a Vite alias
mdx: resolvedReact2.mdx ?? fileURLToPath(import.meta.resolve("@mdx-js/react"))

The fix for mdx (fileURLToPath + alias) was applied but the same treatment was never applied to providerImportSource.

To reproduce

  1. Create a Storybook project with @storybook/react-vite, can be done in an empty dir
  2. Downgrade to Vite 5
  3. Start Storybook — the error appears immediately

Expected behavior

The MDX compiler should receive either a package specifier (@storybook/addon-docs/mdx-react-shim) or a plain absolute path, not a file:// URL.

Suggested fix

In src/preset.ts (and the Vite MDX plugin), wrap the import.meta.resolve() call with fileURLToPath, and add @storybook/addon-docs/mdx-react-shim to the Vite alias map — exactly as is already done for @mdx-js/react:

+ import { fileURLToPath } from 'node:url';

  mdxCompileOptions: {
-   providerImportSource: import.meta.resolve("@storybook/addon-docs/mdx-react-shim"),
+   providerImportSource: fileURLToPath(import.meta.resolve("@storybook/addon-docs/mdx-react-shim")),
  }

Workaround

For anyone facing the issue, add a viteFinal to .storybook/main.ts that strips the file:// protocol from import specifiers before Vite's import analysis runs:

viteFinal: async (config) => ({
  ...config,
  plugins: [
    ...(config.plugins || []),
    {
      name: "resolve-file-urls",
      resolveId(id: string) {
        if (id.startsWith("file://")) return id.replace("file://", "");
      },
    },
  ],
}),

Reproduction link

Reproduction steps

No response

System

-

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions