usebruno/bruno · error · Error

Cannot find module ${filename}

Error message

Cannot find module ${filename}

What it means

Thrown by the QuickJS local-module loader shim after the path-traversal check passed but fs.existsSync(filePath) returned false. The filename (with .js appended if no extension was given) does not exist on disk under collectionPath.

Source

Thrown at packages/bruno-js/src/sandbox/quickjs/shims/local-module.js:23

const addLocalModuleLoaderShimToContext = (vm, collectionPath) => {
  let loadLocalModuleHandle = vm.newFunction('loadLocalModule', function (module) {
    const filename = vm.dump(module);

    // Check if the filename has an extension
    const hasExtension = path.extname(filename) !== '';
    const resolvedFilename = hasExtension ? filename : `${filename}.js`;

    // Resolve the file path and check if it's within the collectionPath
    const filePath = path.resolve(collectionPath, resolvedFilename);
    const relativePath = path.relative(collectionPath, filePath);

    // Ensure the resolved file path is inside the collectionPath
    if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
      throw new Error('Access to files outside of the collectionPath is not allowed.');
    }

    if (!fs.existsSync(filePath)) {
      throw new Error(`Cannot find module ${filename}`);
    }

    let code = fs.readFileSync(filePath).toString();

    return marshallToVm(code, vm);
  });

  vm.setProp(vm.global, '__brunoLoadLocalModule', loadLocalModuleHandle);
  loadLocalModuleHandle.dispose();
};

module.exports = addLocalModuleLoaderShimToContext;

View on GitHub (pinned to 9bdd81c7bd)

Solutions

  1. Confirm the file exists with the exact name and case under the collectionPath.
  2. Remember the shim appends .js — name your local module file with a .js extension, or pass the full filename including extension.
  3. If using TypeScript, transpile to .js first or require the compiled output.

Example fix

// before — only helper.ts exists
crypto.require('./helper'); // -> Cannot find module helper

// after — either rename to helper.js or pass the extension
crypto.require('./helper.js'); // after creating helper.js
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs'); const path = require('path');
function resolveLocal(name, root) {
  const file = path.extname(name) ? name : name + '.js';
  const full = path.join(root, file);
  if (!fs.existsSync(full)) throw new Error('missing: ' + full);
  return full;
}

Type guard

const fileExists = (p) => { try { return fs.statSync(p).isFile(); } catch { return false; } };

Try / catch

try { const m = require('./helper'); }
catch (err) {
  if (/Cannot find module/.test(err.message)) {
    // create the file or fix the name
  } else throw err;
}

Prevention

When it happens

Trigger: require('./missing-file') or require('./helper') when ./helper.js does not exist in the collection directory inside a QuickJS-sandboxed script.

Common situations: File was renamed or deleted; case mismatch on case-sensitive filesystems; the .js extension was expected but the file is .ts/.mjs and the shim only appends .js; the require path is relative to the wrong base (the shim resolves against collectionPath, not the calling file's directory).

Related errors


AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13). Data as JSON: /api/errors/357c1c9d476eac16. Report an issue: GitHub.