mochajs/mocha · error · Error

Unsupported URL protocol "${parsed.protocol}". Only "file:"

Error message

Unsupported URL protocol "${parsed.protocol}". Only "file:" URLs are supported.

What it means

When importing ESM files, Mocha's `resolveFile` accepts either a plain filesystem path or a URL string. If the input parses as a URL whose protocol is not `file:` (e.g. `http:`, `https:`, `data:`), it throws this error because Mocha can only load specs from the local filesystem.

Source

Thrown at lib/nodejs/esm-utils.cjs:159

}

function dealWithExports(module) {
  if (module.default) {
    return module.default;
  } else {
    return { ...module, default: undefined };
  }
}

const resolveFile = (file) => {
  if (URL.canParse(file)) {
    const parsed = new URL(file);
    // Single-letter "protocols" (e.g. "d:") are Windows drive letters, not URL schemes
    if (parsed.protocol.length > 2) {
      if (parsed.protocol === "file:") {
        return url.fileURLToPath(parsed);
      }
      throw new Error(
        `Unsupported URL protocol "${parsed.protocol}". Only "file:" URLs are supported.`,
      );
    }
  }
  return path.resolve(file);
};

exports.loadFilesAsync = async (
  files,
  preLoadFunc,
  postLoadFunc,
  esmDecorator,
) => {
  for (const file of files) {
    preLoadFunc(file);
    const result = await exports.requireOrImport(
      resolveFile(file),
      esmDecorator,

View on GitHub (pinned to 6bcbee4fd9)

Solutions

  1. Pass a filesystem path instead of a URL: `mocha ./test/spec.mjs`.
  2. Convert remote URLs to local files first (download or resolve to the on-disk path).
  3. For file URLs, the `file:` scheme is fine — ensure the scheme is exactly `file:` (e.g. `file:///abs/path/spec.mjs`).
  4. Audit .mocharc/spec glob configuration for accidentally included URLs.

Example fix

// before (.mocharc.json)
{ "spec": ["https://example.com/tests/main.spec.mjs"] }

// after
{ "spec": ["./tests/main.spec.mjs"] }
Defensive patterns

Strategy: validation

Validate before calling

function assertLoadableSpec(file) {
  try {
    const u = new URL(file);
    if (u.protocol.length > 2 && u.protocol !== 'file:') {
      throw new Error(`Spec must be a path or file: URL, got ${u.protocol}`);
    }
  } catch (e) {
    if (!(e instanceof TypeError)) throw e; // TypeError = not a URL, plain path is fine
  }
}

Type guard

const isFileUrlOrPath = (f) => {
  try { return new URL(f).protocol === 'file:'; } catch { return true; }
};

Try / catch

try {
  await importEsm(resolveFile(spec));
} catch (err) {
  if (err.message.startsWith('Unsupported URL protocol')) {
    console.error('Convert remote URLs to local file paths before running specs.');
  }
  throw err;
}

Prevention

When it happens

Trigger: Passing `mocha 'https://example.com/test.mjs'` or another remote URL as a spec; passing a URL with an exotic scheme (`webpack:`, `data:`); on Windows, a path like `D:\foo` can be misread as a URL but single-letter drive protocols are correctly allowed.

Common situations: CI configs where the spec path variable contains a URL; accidentally pasting a CDN/bundle URL into .mocharc spec arrays; tooling that resolves test files to `http://localhost/...` dev-server URLs instead of paths.


AI-assisted analysis of mochajs/mocha@6bcbee4fd9 (2026-09-01). Data as JSON: /api/errors/d9a51ca4fdac15e6. Report an issue: GitHub.