usebruno/bruno · error · Error

Cannot find module

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.

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.

Appendix: 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)