vitejs/vite · error · Error

[module runner] Failed to load

Error message

[module runner] Failed to load "${url}"${importer ? ` imported from ${importer}` : ''}

What it means

In `directRequest`, after fetching module metadata the runner reads `fetchResult.code`. If `code == null` (and the module is not externalized), the runner cannot evaluate it and throws a load-failure error, including the importing module for context. The root cause is the transport returning a fetch result with no code.

Solutions

  1. Check the dev server logs for the transform error of the named module and fix the underlying syntax/transform error.
  2. If using a custom transport, ensure `fetchModule` throws on real errors instead of returning `{ code: null }`.
  3. Verify the module path (`url`) resolves to a real, readable file.
  4. Disable plugins one-by-one to find a `load`/`transform` hook returning null for that module.

Example fix

// before (custom transport)
async invoke('fetchModule', [url]) {
  try { return { code: await readFileMaybe(url), url } }
  catch { return { code: null, url } } // hides the error
}
// after
async invoke('fetchModule', [url]) {
  const code = await fs.readFile(url, 'utf-8') // throws on missing - surfaces real error
  return { code, url }
}
Defensive patterns

Strategy: try-catch

Validate before calling

function assertFetchResultHasCode(result: unknown, url: string) {
  if (!result || typeof result !== 'object') return
  if (!('externalize' in result) && (result as any).code == null) {
    throw new Error(`fetchModule returned no code for ${url} - check transform/load errors`)
  }
}

Type guard

function isFetchResultWithCode(r: any): boolean {
  return r && ('externalize' in r || typeof r.code === 'string')
}

Try / catch

try {
  return await runner.import(url)
} catch (e) {
  if (e instanceof Error && /Failed to load/.test(e.message)) {
    // inspect dev-server logs for the transform error on the named module; do not blindly retry
  } else throw e
}

Prevention

When it happens

Trigger: The runner transport's `fetchModule` returns a result whose `code` is null/undefined for a non-externalized module. This happens when the dev server fails to transform a file, the file is unreadable, or a custom transport returns an empty result.

Common situations: Importing a file that errors during transformation (syntax error, unsupported syntax) where the server swallows the transform error and returns empty code. Network/filesystem issues in a remote transport. Misbehaving plugin `load` hooks returning null.

Related errors


AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11). Data as JSON: /api/errors/0edd474c7d15ba47. Report an issue: GitHub.

Appendix: source

Thrown at packages/vite/src/module-runner/runner.ts:363

      if (dep[0] === '.') {
        dep = posixResolve(posixDirname(url), dep)
      }
      return request(dep, { isDynamicImport: true })
    }

    if ('externalize' in fetchResult) {
      const { externalize } = fetchResult
      this.debug?.('[module runner] externalizing', externalize)
      const exports = await this.evaluator.runExternalModule(externalize)
      mod.exports = exports
      return exports
    }

    const { code, file } = fetchResult

    if (code == null) {
      const importer = callstack[callstack.length - 2]
      throw new Error(
        `[module runner] Failed to load "${url}"${
          importer ? ` imported from ${importer}` : ''
        }`,
      )
    }

    const createImportMeta =
      this.options.createImportMeta ?? createDefaultImportMeta

    const modulePath = cleanUrl(file || moduleId)
    // disambiguate the `<UNIT>:/` on windows: see nodejs/node#31710
    const href = posixPathToFileHref(modulePath)
    const meta = await createImportMeta(modulePath)
    const exports = Object.create(null)
    Object.defineProperty(exports, Symbol.toStringTag, {
      value: 'Module',
      enumerable: false,
      configurable: false,

View on GitHub (pinned to b4d66fee14)