# Fix NetSuite MODULE_DOES_NOT_EXIST in SuiteScript 2.x

> Source: https://netray.co/erp-help/netsuite-module-does-not-exist-suitescript-2x-error
> Publisher: Netray (netray.co), AI and integration engineering for ERP and manufacturing systems.
> Section: ERP Help

## Short answer

MODULE_DOES_NOT_EXIST is thrown when the SuiteScript 2.x loader cannot resolve a path listed in define() or require(). In practice the cause is almost always a wrong relative path, a missing file in the File Cabinet, a bad N/ module name, or a library that was not deployed with the script.

## Kind

error

## System

netsuite

## Erp

Oracle NetSuite

## Module

SuiteScript 2.x / Module Loading

## Query

NetSuite MODULE_DOES_NOT_EXIST SuiteScript 2.x error

## Alternate Queries

- MODULE_DOES_NOT_EXIST Module does not exist NetSuite
- SuiteScript 2.1 define cannot find custom module path
- NetSuite script module not found after SDF deploy
- SuiteScript require relative path library not found

## Applies To

SuiteScript 2.0 and 2.1, all script types, File Cabinet and SDF (SuiteCloud Development Framework) deployments

## Steps

### How to fix MODULE_DOES_NOT_EXIST

**Items:**

- Read the full error message: it names the module string that failed to load, for example ./lib/utils or N/recrod. Copy that exact string.
- If it starts with N/, check spelling and case against the SuiteScript 2.x module list (N/record, N/search, N/runtime, N/query, N/https). N/ modules are case sensitive.
- If it is a relative path, open Documents > Files > File Cabinet and confirm the file exists at that path relative to the folder of the script that calls it.
- Check the file extension. NetSuite resolves ./utils to utils.js automatically, so do not include .js, and do not name the file utils.JS or utils.js.txt.
- Check the module's own header. A library loaded with define() must contain a define() call, not just plain functions, and must return its exports.
- In SDF projects, confirm the library file is under /SuiteScripts/ in the project and listed in deploy.xml or covered by the file import, then redeploy with suitecloud project:deploy.
- For paths starting with /SuiteScripts/, remember they are absolute from the File Cabinet root. A script moved to a different account folder keeps working only with absolute paths.
- Clear the cached script by saving the script record again (or redeploy), then rerun and read the Execution Log.

## Sections

### How the SuiteScript 2.x loader resolves a path

**Body:**

SuiteScript 2.x uses an AMD style loader. When your entry point script declares define(['N/record', './lib/helpers'], function(record, helpers){...}), NetSuite resolves each string at load time, before any of your code runs. N/ names map to built-in modules. Everything else is treated as a File Cabinet path.

A path beginning with ./ or ../ is relative to the folder of the file that contains the define call, not to the folder of the script record or the deployment. A path beginning with / is absolute from the File Cabinet root. This is why a script that works in /SuiteScripts/Sales/ breaks when the same file is copied into /SuiteScripts/Sales/v2/ without moving its libraries.

Because resolution happens at load, the error appears even if the missing module would only be used on a rare code path. The failure is reported against the entry point, which sometimes hides the fact that the broken define is in a library that the entry point loads in turn.

**Code:**

/**
 * @NApiVersion 2.1
 * @NScriptType UserEventScript
 */
define(['N/record', './lib/helpers'], (record, helpers) => {
  const afterSubmit = (ctx) => { helpers.log(ctx.newRecord.id); };
  return { afterSubmit };
});

### Common causes seen in real accounts

**Body:**

The first group is typing. N/search misspelled as N/serach, N/Record with a capital R, or a path with a stray space. The second group is File Cabinet drift: a developer renames or moves a library folder through the UI, and every script that used a relative path to it breaks on the next load.

The third group is deployment. A SuiteApp or SDF project deploys the entry script but not the library because the library was never added to the project, or it sits in a folder excluded from the manifest. The sandbox works because someone uploaded the file by hand there, while production fails. Compare File Cabinet listings between sandbox and production.

The fourth group is a library that exists but does not define itself. If a file is a plain script with no define() wrapper, the loader finds the file but cannot treat it as a module. Some versions surface this as MODULE_DOES_NOT_EXIST with the path of the file, which confuses people who can plainly see the file in the cabinet.

### Using path mappings and config files

**Body:**

For larger code bases, define a requirejs style configuration with the @NModuleScope and the config JSON referenced by the @NAmdConfig tag. A JSDoc line such as @NAmdConfig /SuiteScripts/config.json lets you give aliases to deep folders, so define(['lib/helpers']) resolves from one place.

If you use aliases, the MODULE_DOES_NOT_EXIST message will list the alias, not the final path. Check the paths object in the config and confirm the target is a folder or a file without extension. A common mistake is pointing an alias at a file with .js included.

Keep the config file in a stable location. If the config itself cannot be found, every module that depends on an alias fails, and the error looks widespread when it is a single bad path.

**Code:**

- {
  "paths": {
    "lib": "/SuiteScripts/Common/lib"
  }
}

### Debugging approach that saves time

**Body:**

Strip the define list to only N/ modules and run. If it loads, add custom modules back one at a time. This isolates the exact failing dependency in minutes instead of reading the whole stack. In Script Debugger, load the entry file directly; it reports module errors synchronously.

For SDF work, run suitecloud project:validate before deploy. It checks object references and some file dependencies and catches the library that was left out of the project. Add a CI step so library files are required to exist in the project directory tree.

## Pitfalls

- Including .js in the define path: use ./lib/helpers, not ./lib/helpers.js.
- Assuming relative paths are relative to the script record: they are relative to the file containing define().
- Fixing the sandbox by uploading a file by hand and forgetting to add it to the SDF project.
- Case differences between N/Record and N/record. Built-in module names are lowercase after the slash.
- Moving a folder in the File Cabinet UI without searching for scripts that reference its files by absolute path.
- A library with no define() wrapper, which loads as a file but is not a valid module.

## Ai Angle

An assistant grounded in your NetSuite code base can list every define() dependency in a script, compare it to the File Cabinet and SDF manifest, and tell you which referenced file is absent or misnamed before you deploy. ERPray is read-only by default, so it inspects metadata and file listings rather than editing scripts. A developer still reviews and deploys the fix.

## Faq

### Why does it work in sandbox but fail in production?

**Answer:** The library file almost always exists in sandbox because it was uploaded manually or refreshed from an older production copy, but it was never part of the SDF project that deployed to production. Compare the File Cabinet folders in both accounts and add the missing file to the project.

### Do I need the .js extension in define paths?

**Answer:** No. The loader appends .js for you. Including it causes the loader to look for a file named helpers.js.js and raises MODULE_DOES_NOT_EXIST. Use the bare path, relative or absolute, and keep the real file name ending in .js.

### Is SuiteScript 2.1 different from 2.0 here?

**Answer:** Module resolution works the same way. The difference is the runtime: 2.1 supports modern JavaScript syntax. Mixed projects can fail if a 2.0 library is required from 2.1 code with a different NApiVersion tag, so keep tags consistent when you debug path errors.

### Can a typo in an unused code path cause this?

**Answer:** Yes. Dependencies in define() are loaded eagerly when the script initialises, so a bad module string fails the whole script even if the function that uses it never runs. Remove or correct the entry rather than relying on the branch being skipped.

## Search terms

MODULE_DOES_NOT_EXIST NetSuite, SuiteScript 2.x module not found, NetSuite define path error, SuiteScript relative path library, NetSuite AMD config NApiVersion, SDF deploy missing file, NetSuite custom module not found, suitecloud project deploy library

---
Talk to an engineer: https://netray.co/contact?intent=erp_ai | Machine catalog: https://netray.co/agent/catalog.json
