vitejs/vite · error · Error

[module runner] "import.meta.resolve" is not supported.

Error message

[module runner] "import.meta.resolve" is not supported.

What it means

The default module-runner import.meta object implements `resolve()` as a function that always throws. Resolution of arbitrary specifiers at runtime requires filesystem/resolve machinery that the default runner does not provide. The Node-specific variant (`createNodeImportMeta`) does implement `resolve`, so the throw only occurs under the default meta.

Solutions

  1. Pass a custom `createImportMeta` to the ModuleRunner that supplies a working `resolve` (the runner's `createImportMetaResolver` helper can back it).
  2. Use the Node module-runner evaluator path (`createNodeImportMeta`) which implements `resolve`.
  3. Avoid `import.meta.resolve` in runner-executed code; resolve specifiers at build time or via the runner transport instead.

Example fix

// before
new ModuleRunner({ transport, /* default createImportMeta - resolve throws */ })
// module calls: import.meta.resolve('./foo')

// after
import { createNodeImportMeta } from 'vite/module-runner'
new ModuleRunner({ transport, createImportMeta: createNodeImportMeta })
Defensive patterns

Strategy: validation

Validate before calling

import { createNodeImportMeta } from 'vite/module-runner'
function runnerOptionsNeedsNodeResolve(opts: { createImportMeta?: unknown }) {
  // if no custom createImportMeta provided AND code uses import.meta.resolve, swap in the Node variant
  return opts.createImportMeta == null
}
// usage: if (runnerOptionsNeedsNodeResolve(opts)) opts.createImportMeta = createNodeImportMeta

Type guard

function importMetaResolveAvailable(meta: any): boolean {
  try { return typeof meta.resolve === 'function' && meta.resolve !== createDefaultImportMetaResolveStub() } catch { return false }
}

Try / catch

try {
  return import.meta.resolve(id)
} catch (e) {
  if (e instanceof Error && /import.meta.resolve.*not supported/.test(e.message)) {
    // resolve via an alternative (e.g. node:module createRequire)
  } else throw e
}

Prevention

When it happens

Trigger: Calling `import.meta.resolve(id)` in code executed by a module runner that was constructed with the default `createImportMeta` (no custom `createImportMeta` option and not the Node evaluator path).

Common situations: Sharing a module between a bundler build and the runner where the bundler supports `import.meta.resolve` but the runner default does not. Library code that probes `import.meta.resolve` for feature detection.

Related errors


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

Appendix: source

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

    throw new Error(
      `[module runner] Dynamic access of "import.meta.env" is not supported. Please, use "import.meta.env.${String(p)}" instead.`,
    )
  },
})

export function createDefaultImportMeta(
  modulePath: string,
): ModuleRunnerImportMeta {
  const href = posixPathToFileHref(modulePath)
  const filename = modulePath
  const dirname = posixDirname(modulePath)
  return {
    filename: isWindows ? toWindowsPath(filename) : filename,
    dirname: isWindows ? toWindowsPath(dirname) : dirname,
    url: href,
    env: envProxy,
    resolve(_id: string, _parent?: string) {
      throw new Error('[module runner] "import.meta.resolve" is not supported.')
    },
    // should be replaced during transformation
    glob() {
      throw new Error(
        `[module runner] "import.meta.glob" is statically replaced during ` +
          `file transformation. Make sure to reference it by the full name.`,
      )
    },
  }
}

/**
 * Create import.meta object for Node.js.
 */
export function createNodeImportMeta(
  modulePath: string,
): ModuleRunnerImportMeta {
  const defaultMeta = createDefaultImportMeta(modulePath)

View on GitHub (pinned to b4d66fee14)