Hi n8n Community,
I’m encountering a persistent “Cannot find module” error when trying to use external JavaScript modules (like is-odd
or pdf-lib
) in the Code node. I’ve been through extensive troubleshooting and would appreciate any insights or help.
Describe the problem/error/question:
The Code node (JavaScript) consistently fails to load external npm modules, even simple ones like is-odd
. This occurs despite N8N_FUNCTION_ALLOW_EXTERNAL
being set (currently to *
for testing, previously also with specific module lists).
Interestingly, if I switch the Code node to Python (Beta) mode, importing and using standard Python libraries like json
and sys
works perfectly. This suggests the issue is specific to the JavaScript/Node.js module loading mechanism.
What is the error message (if any)?
When the Code node (JavaScript) attempts require('is-odd');
with N8N_RUNNERS_ENABLED=false
and N8N_DISABLE_SANDBOX=false
(or true
, see below), the n8n GUI typically shows:
JSON{ "errorMessage": "Cannot find module 'is-odd' [line X]", "errorDescription": "VMError", "errorDetails": {}, "n8nDetails": { "nodeName": "Code", "nodeType": "n8n-nodes-base.code", "nodeVersion": 2, "n8nVersion": "1.94.1 (Self Hosted)", "stackTrace": [ "VMError: Cannot find module 'is-odd'", " at Resolver.resolveFull (/usr/local/lib/node_modules/n8n/node_modules/.pnpm/@[email protected]/node_modules/@n8n/vm2/lib/resolver.js:126:9)", " at Resolver.resolve (/usr/local/lib/node_modules/n8n/node_modules/.pnpm/@[email protected]/node_modules/@n8n/vm2/lib/resolver.js:121:15)", " at resolve (/usr/local/lib/node_modules/n8n/node_modules/.pnpm/@[email protected]/node_modules/@n8n/vm2/lib/nodevm.js:317:21)", " at VM2 Wrapper.apply (/usr/local/lib/node_modules/n8n/node_modules/.pnpm/@[email protected]/node_modules/@n8n/vm2/lib/bridge.js:490:11)", " at requireImpl (/usr/local/lib/node_modules/n8n/node_modules/.pnpm/@[email protected]/node_modules/@n8n/vm2/lib/setup-node-sandbox.js:90:19)", " at require (/usr/local/lib/node_modules/n8n/node_modules/.pnpm/@[email protected]/node_modules/@n8n/vm2/lib/setup-node-sandbox.js:171:10)", " at /usr/local/lib/node_modules/n8n/node_modules/.pnpm/n8n-nodes-base@file+packages+nodes-base_@[email protected]_asn1.js@5_12b981d6b49d407a163f4d5244314033/node_modules/n8n-nodes-base/dist/nodes/Code:X:Y", " ...", " at NodeVM.run (/usr/local/lib/node_modules/n8n/node_modules/.pnpm/@[email protected]/node_modules/@n8n/vm2/lib/nodevm.js:497:23)" ] } }
(Line numbers X, Y in the GUI stack trace vary slightly based on the exact code in the node.)
Sometimes, the error.code
in the returned JSON (when catching the error within the Code node) shows ENOTFOUND
.
If N8N_RUNNERS_ENABLED=true
, the stack trace points to /@n8n+task-runner/dist/js-task-runner/require-resolver.js
instead of vm2
directly. The error remains “Cannot find module”.
Please share your workflow:
The test workflow is minimal:
- Start node
- Code node (JavaScript)
JSON{ "nodes": [ { "parameters": {}, "name": "Start", "type": "n8n-nodes-base.start", "typeVersion": 1, "position": [ 250, 300 ] }, { "parameters": { "language": "javascript", "jsCode": "// Test Code for 'is-odd'\nconsole.log(\"Code Node: Attempting to require 'is-odd'.\");\nconsole.log(\"NODE_PATH from process.env: \", process.env.NODE_PATH);\nconsole.log(\"N8N_FUNCTION_ALLOW_EXTERNAL from process.env: \", process.env.N8N_FUNCTION_ALLOW_EXTERNAL);\n\nlet output = {};\ntry {\n const isOdd = require('is-odd');\n output.moduleFound = true;\n output.isOddResult = isOdd(3);\n output.message = \"Module 'is-odd' successfully loaded and executed.\";\n console.log(\"Module 'is-odd' successfully loaded.\");\n} catch (error) {\n console.error(\"Error loading 'is-odd':\", error);\n output.moduleFound = false;\n output.error = {\n message: error.message,\n stack: error.stack,\n code: error.code\n };\n throw error; // Re-throw to mark node as failed and see error in GUI\n}\nreturn output;" }, "name": "Code", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 450, 300 ] } ], "connections": { "Start": { "main": [ [ { "node": "Code", "type": "main", "index": 0 } ] ] } } }
Share the output returned by the last node: As shown in the error message section, the Code node fails and the output typically includes the error object.
Information on your n8n setup:
- n8n version:
1.94.1
(from Docker imagen8nio/n8n:latest
at the time of testing) - Database (default: SQLite): SQLite
- n8n EXECUTIONS_PROCESS setting (default: own, main): Tested with
N8N_RUNNERS_ENABLED=true
andN8N_RUNNERS_ENABLED=false
. The error persists in both modes, with stack traces pointing totask-runner
orvm2
respectively. - Running n8n via (Docker, npm, n8n cloud, desktop app): Docker (initially via Unraid’s Docker management, now with a direct
docker-compose
setup for cleaner testing). - Operating system:
- Host: Unraid OS (Slackware-based)
- Container: Alpine Linux (from
n8nio/n8n:1.94.1
image), Node.js v20.19.2
Relevant docker-compose.yml
:
`YAMLservices:
n8n:
# build: /path/to/my/custom/Dockerfile # Tried with Dockerfile to npm install -g modules
image: n8nio/n8n:1.94.1 # Currently testing with base image
container_name: n8n
restart: unless-stopped
ports:
- “5678:5678”
environment:
- GENERIC_TIMEZONE=Europe/Berlin
- TZ=Europe/Berlin
- WEBHOOK_URL=https:///
- NODE_ENV=production
- N8N_LOG_LEVEL=debug
- N8N_FUNCTION_ALLOW_EXTERNAL=* # Also tested with specific list: pdf-lib,node-fetch,pdf-parse,is-odd,pdf2json
- N8N_FUNCTION_ALLOW_BUILTIN=fs
- N8N_RUNNERS_ENABLED=false # Tested with true and false
- N8N_DISABLE_SANDBOX=false # Tested with true and false
- NODE_PATH=/usr/local/lib/node_modules # Tested when attempting global install via Dockerfile
volumes:
- /mnt/cache/appdata/n8n:/home/node/.n8n # Host path permissions are 1000:1000 rwxrwxr-x
networks:
- n8n_network
networks:
n8n_network:
driver: bridge`
Summary of Troubleshooting Steps & Findings:
N8N_FUNCTION_ALLOW_EXTERNAL
: Confirmed viaenv
in container andconsole.log(process.env.N8N_FUNCTION_ALLOW_EXTERNAL)
in Code node that the variable is correctly set and read by n8n.- Host Volume Permissions: Confirmed
/mnt/cache/appdata/n8n
on host is1000:1000
withrwxrwxr-x
permissions. - Network Connectivity: Container can ping and
wget
fromregistry.npmjs.org
. - Manual npm install in container:
npm install is-odd
works in/home/node/
(non-mounted path) but not in/usr/local/lib/node_modules/n8n
(due toEUNSUPPORTEDPROTOCOL workspace:
error, likely due to n8n’s monorepo structure). - Dockerfile
npm install -g
: Attempted to build a custom image installingis-odd
,pdf-lib
etc. globally usingnpm install -g
. Modules appear in/usr/local/lib/node_modules
inside the container.NODE_PATH
was set to this directory. The “Cannot find module” error in Code node persisted. N8N_RUNNERS_ENABLED
: Error occurs whethertrue
orfalse
. Stack trace source changes accordingly.N8N_DISABLE_SANDBOX
: Setting totrue
(with runnersfalse
) still results in “Cannot find module ‘is-odd’” with a stack trace pointing tovm2/lib/resolver.js
. This suggestsN8N_DISABLE_SANDBOX=true
might not fully bypassvm2
’s module resolution or that the issue is even more fundamental.- Python Test: A Code node set to Python successfully imports and uses standard libraries (
json
,sys
). - No Module Cache Found: No
node_modules
or.npm
cache directories for the external modules are found within the mounted/home/node/.n8n
directory.
Key Questions:
- Given
N8N_DISABLE_SANDBOX=true
andN8N_RUNNERS_ENABLED=false
, and modules globally installed withNODE_PATH
set, why wouldrequire('is-odd')
still fail with aVMError
pointing tovm2/lib/resolver.js
? DoesN8N_DISABLE_SANDBOX=true
not fully bypassvm2
for module resolution? - Where does n8n (v1.94.1, Node.js v20, Alpine) attempt to download/cache modules specified in
N8N_FUNCTION_ALLOW_EXTERNAL
when it’s not using globally installed ones? Why is this process failing silently (no download errors in logs, no cache files created in/home/node/.n8n
)? - Could the
ENOTFOUND
error code (seen intermittently in GUI for the JS error) provide a clue, despite network connectivity being verified for the container? - Are there any known issues or specific configurations required for n8n’s JS module loading on Alpine Linux with Node.js v20 that could explain this behavior, especially when Python standard library imports work fine?
Any help or pointers would be greatly appreciated. This is a critical blocker for my PDF processing workflows.
Thank you!