I am trying to do two things, each of them works fine separately, but they do not work together due to problem with setting environmental variable.
First one is checking n8n version using code node:
const version = require(‘/usr/local/lib/node_modules/n8n/package’).version
return [
{
version_n8n: version
}
]
This code to work needs modules enabled by adding environmental variable in the docker compose file:
NODE_FUNCTION_ALLOW_EXTERNAL=*
All works fine at this stage.
Second, checking version of underling sqlite version:
const sqlite3 = require(‘sqlite3’);
const db = new sqlite3.Database(‘:memory:’);
return new Promise((resolve, reject) => {
db.get(‘SELECT sqlite_version() AS version’, (err, row) => {
if (err) return reject(err);
resolve([{ json: { version: row.version } }]);
});
});
This one needs “modules enabled” by adding environmental variable in the docker compose file:
NODE_FUNCTION_ALLOW_EXTERNAL=sqlite3. Again all work fine if this is not connected with the previous node.
Here comes the problem. Having both nodes in one workflow makes one to work improper.
Setting the variable twice, makes the latter one only to work:
NODE_FUNCTION_ALLOW_EXTERNAL=*
NODE_FUNCTION_ALLOW_EXTERNAL=sqlite3
Setting two values at once
NODE_FUNCTION_ALLOW_EXTERNAL=,sqlite3
makes the first code dependent on the setting "" not to work.
Anyway strange that “" does not include “sqlite3” but found recently an explanation "sqlite3 requires compiled native binaries to communicate with operating system, whereas NODE_FUNCTION_ALLOW_EXTERNAL= is natively optimized to handle standard, pure-JavaScript packages”.
Anyway please advise how to set the environmental variable so both code nodes will run without issues.
What is the error message (if any)?
Please share your workflow
(Select the nodes on your canvas and use the keyboard shortcuts CMD+C/CTRL+C and CMD+V/CTRL+V to copy and paste the workflow.)
Share the output returned by the last node
Information on your n8n setup
n8n version: 2.22.5
Database (default: SQLite): SQLite
n8n EXECUTIONS_PROCESS setting (default: own, main): own
Running n8n via (Docker, npm, n8n cloud, desktop app): Docker (Docker Desktop on Windows 10)
Operating system: Windows 10, docker default os by latest Docker Desktop
@megrez7 quick check — are u on n8n 2.x with task runners enabled (default now)? if yes, NODE_FUNCTION_ALLOW_EXTERNAL has to be set on the runner service in ur docker-compose, not the main n8n service — Code nodes execute inside the runner container, so vars on the n8n service get ignored when runners are active. and on the value itself: drop the wildcard and list every module explicitly comma-separated (sqlite3,fs,...) — * is known buggy in 2.x and doesnt cover native compiled modules like sqlite3 regardless.
NODE_FUNCTION_ALLOW_EXTERNAL=*,sqlite3 → n8n,sqlite3 (explicit list, no wildcard — the * doesnt actually cover everything in 2.x and silently breaks combos)
removed the duplicate N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=false line (u had it twice, second one was overriding the first)
then in docker desktop: stop the container, run docker compose up -d again in ur n8n folder to apply the env changes. both code nodes should run in the same workflow after that.
if code 1 (the require('/usr/local/lib/node_modules/n8n/package') one) still complains about the n8n module being disallowed, alt approach is using fs to read the package.json instead — but try the above first.
Good point to clean up the fle. I have tried already explicitly setting both values but it does not work (tested again now) either.
The first node (checking n8n version) returns “Module ‘/usr/local/lib/node_modules/n8n/package’ is disallowed [line 1]”.
Wondering why wildcard works in this case, but “n8n” value not. Do we need anything more specific, or just some different value for NODE_FUNCTION_ALLOW_EXTERNAL?
yeah confirmed — the allowlist matches against the require string, and require('/usr/local/lib/node_modules/n8n/package') is an absolute path not a package name, so listing n8n doesnt match it. wildcard works because it bypasses the match entirely. cleanest fix is switch code 1 to use fs to read the package.json instead — then u only need sqlite3 in the external list and fs in the builtin list.
another option besides fs or @kjooleng’s wildcard — just export the version as a plain env var in ur compose and read it via process.env, no require at all:
trade-off is u bump the N8N_VERSION value manually when u upgrade n8n — but no require, no fs, no wildcard parsing edge cases. pick whichever feels cleanest for ur workflow.
Two things are biting you, and the fix is to drop * altogether.
You can’t set the same env var twice — Docker keeps only the last one, so =* then =sqlite3 collapses to just =sqlite3, which is why the first node breaks.
* is a wildcard only when it’s the entire value. The moment you make it a list (,sqlite3), n8n reads each entry as a literal package name, so * becomes a literal "" that matches nothing — that’s why the n8n-version node dies in the combined form.
Clean fix — one named allowlist, and require the n8n package by name instead of an absolute path:
Set a single value: NODE_FUNCTION_ALLOW_EXTERNAL=n8n,sqlite3
Change the first Code node from the absolute path to a module require:
const version = require(‘n8n/package.json’).version;
return [{ json: { version_n8n: version } }];
Now both packages are explicitly allowed by name, there’s no wildcard to conflict, and you’re not exposing every module to your Code nodes — which you don’t want from a security angle anyway.
Aside: NODE_FUNCTION_ALLOW_EXTERNAL is for npm packages; if you ever need a Node built-in (crypto, fs…), that’s the separate NODE_FUNCTION_ALLOW_BUILTIN var. sqlite3 is external, so you’re in the right place.
To obtain the n8n’s version, much easier to use Execute Command node with n8n --version command. However, this node is disabled by default.
As for the SQLite.. It’s generally not a good DB for production use, better to use Postgres (especially if you already have a Docker Compose), then you can use SELECT version(); from within the Postgres node