cube-js/cube · error · UserError

'${modulePath}' restricted

Error message

'${modulePath}' restricted

What it means

DataSchemaCompiler.resolveModuleFile resolves a module import from data model JS files to a path under node_modules. If the resolved absolute path escapes the project's node_modules directory (e.g. via '../' traversal or an absolute path), and allowNodeRequire is not enabled, the compiler refuses the import with UserError ''${modulePath}' restricted'. This is a sandbox/security guard so data models can only load whitelisted packages.

Source

Thrown at packages/cubejs-schema-compiler/src/compiler/DataSchemaCompiler.ts:1003

    if (!currentFile.isModule && localImport) {
      const fileName = localImport[1].match(/^.*\.js$/) ? localImport[1] : `${localImport[1]}.js`;
      const foundFile = toCompile.find((f) => f.fileName === fileName);
      if (!foundFile) {
        throw new UserError(`Required import for ${fileName} is not found`);
      }
      return foundFile;
    }

    const nodeModulesPath = path.resolve('node_modules');
    let absPath = currentFile.isModule ?
      path.resolve('node_modules', path.dirname(currentFile.fileName), modulePath) :
      path.resolve('node_modules', modulePath);

    if (!absPath.startsWith(nodeModulesPath)) {
      if (this.allowNodeRequire) {
        return null;
      }
      throw new UserError(`'${modulePath}' restricted`);
    }
    const packagePath = absPath.replace(nodeModulesPath, '').split('/').filter(s => !!s)[0];
    if (!packagePath) {
      if (this.allowNodeRequire) {
        return null;
      }
      throw new UserError(`'${modulePath}' is incorrect`);
    }
    if (!this.isWhiteListedPackage(packagePath)) {
      if (this.allowNodeRequire) {
        return null;
      }
      throw new UserError(`Package '${packagePath}' not found`);
    }
    if (fs.existsSync(absPath)) {
      const stat = fs.lstatSync(absPath);
      if (stat.isDirectory()) {
        absPath = path.resolve(absPath, 'index.js');

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Move the imported file into the project so it resolves under node_modules, or into the schema folder for relative imports
  2. Enable allowNodeRequire in compiler options if arbitrary Node requires are acceptable in your environment
  3. Inline or re-export the needed code through a whitelisted npm package installed in node_modules

Example fix

// before
import { formatDate } from '../shared/format';

// after
import { formatDate } from './format'; // file placed inside the schema folder
Defensive patterns

Strategy: validation

Validate before calling

const path = require('path');
function isAllowedImport(modulePath) {
  const abs = path.resolve('node_modules', modulePath);
  return abs.startsWith(path.resolve('node_modules'));
}
if (!isAllowedImport('./../shared/foo')) throw new Error('import escapes node_modules');

Try / catch

try {
  await compiler.compile();
} catch (e) {
  if (String(e.message).endsWith("' restricted")) {
    console.error('Data model import outside node_modules:', e.message);
  }
}

Prevention

When it happens

Trigger: Importing a module from a JS data model whose resolved path is not under node_modules: relative imports like '../shared/foo.js' that climb out of the schema folder, absolute paths, or imports that path.resolve normalizes outside node_modules while compile flags run without allowNodeRequire.

Common situations: Developers moving shared schema helpers outside the project, using path traversal in require/import statements, or running in environments (Cube Cloud / compiler API) where allowNodeRequire is disabled by default.

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/a182736306773ec9. Report an issue: GitHub.