Debugging custom modules/nodes/credentials

I’m new to TS and the n8n codebase. I’m creating some custom modules with custom nodes and credentials.

Sometimes some errors occur and it’s really hard to debug them because I don’t know how to debug them. For instance, I don’t even know if they were properly loaded.

So starting from the basics, is there a way to check all the modules loaded, and the nodes and credentials they loaded?

Further on, are there any tips on how to debug them? Is it possible to use something like the VS Code debugger to debug it?

Sharing My Findings

Here is how I set up a VSCode environment for developing and debugging n8n and a custom nodes package.

Many of it is based on the post https://community.n8n.io/t/how-to-run-n8n-in-debug-mode-with-vscode/, but with a lot of things that I had figured out, partially for not being a skilled Typescript programmer.

There are 2 different parts: the n8n itself, and a custom module that I will call n8n-nodes-custom (from here).

So, I created a folder to keep everything in, and inside I cloned n8n repo, installed its’s dependencies, then created the n8n-nodes-custom from the template repo.

The actual commands are something like this (I don’t remember exactly how I did it). It assumes to have all dev dependencies installed (npm, lerna, dev tools) from the contributing guide.

mkdir n8n-root
cd n8n-root

git clone https://github.com/n8n-io/n8n.git
git clone https://github.com/n8n-io/n8n-nodes-starter.git n8n-nodes-custom

cd n8n
lerna bootstrap --hoist
npm run build

# link the custom module here, so n8n can detect and load it
ln -sr ../n8n-nodes-custom ./node_modules

cd ../n8n-nodes-custom
npm install
npm run build

# now we can run it like
cd ..
./n8n/packages/cli/bin/n8n

VSCode setup

Just reminding, the n8n project is composed by many node packages in the folder packages. Running lerna exec npm run build will run, sequentially, the npm run build command for every package that has the build command in its package.json. Some packages are faster to build (like cli) and some of them can be very time consuming, like the editor-ui. So depending on what you are working on, it’s better to just build what you need.

With above setup, here is the VSCode config for it:

n8n-root/n8n.code-workspace

To be saved in the n8n-root folder

{
	"folders": [
		{
			"path": "."
		},
		{
			"path": "n8n"
		},
		{
			"path": "n8n-nodes-custom"
		}

	],
	"settings": {}
}

n8n-root/.vscode/tasks.json (for build tasks)

3 tasks and 1 group:

  • One for building (compiling) the whole n8n package.
  • As the build of some parts are slow, there is an example of tash to build one specific part of the n8n, in this case, the cli.
  • And the third one is to build the custom package.
  • The last one is a group of tasks. You can group all tasks that you want to run before a debug session, like building all components that you are actively developing. It can be done in parallel ("dependsOrder": "parallel"), or sequential ("dependsOrder": "sequence").
{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "npm",
			"script": "build",
			"group": "build",
			"label": "npm: build n8n",
			"detail": "lerna exec npm run build",
			"problemMatcher": [ "$tsc" ],
			"options": {"cwd": "${workspaceFolder}/n8n"},
			"path": "n8n",
		},
		{
			"type": "npm",
			"script": "build",
			"group": "build",
			"label": "npm: build cli",
			"detail": "npm run build [cli]",
			"problemMatcher": [ "$tsc" ],
			"options": {"cwd": "${workspaceFolder}/n8n/packages/cli"},
			"path": "n8n/packages/cli"
		},
		{
			"type": "npm",
			"script": "build",
			"group": "build",
			"label": "npm: build n8n-nodes-custom",
			"detail": "npm run build [custom]",
			"problemMatcher": [ "$tsc" ],
			"options": {"cwd": "${workspaceFolder}/n8n-nodes-custom"},
			"path": "n8n-nodes-custom"
		},
		{
			"label": "build all",
			"dependsOrder": "parallel",
			"dependsOn": [
				"npm: build n8n-nodes-custom",
			]
		}
	]
}

n8n-root/.vscode/launch.json (for debugging)

There are 3 options here for debugging:

  • The last one will run in dev mode. It means it will automatically watch for changes in the code and recompile it. Usually, it has poor debug integrations. It’s better for running in the terminal. I leave it here just in case.
  • The other 2 are almost the same, but one will run a task defined in tasks.json that will run the build scripts that are needed. In particular, in tasks.json, the build all is a task group, that you will name all the other tasks you want to run. If you are just developing custom nodes, the n8n itself, or both, you can choose there. Reminding that building all n8n is time-consuming, so it’s better explicitly to tell which parts of the n8n you want to build for efficiency.
  • The "env": { "EXECUTIONS_PROCESS": "main" } was taken from here

I have a lot of headaches trying to debug the Typescript code. There were a few tricks that proved to be useful:

  • In the package.json n8n part where you add the nodes and credentials, you can add the .ts file instead of the compiled .js. E.g. instead of "dist/nodes/Cron.node.js", you can add "nodes/Cron.node.ts" (without the dist/ in the path, and using .ts extension). The loading time will be a lot slower, as it seems that it compiles the TS file and it’s requirements when importing the file. But if you are having issues with debugging (like being able to put a breakpoint in the code), this may help. Adding it together with the JS version (both the .js and the .ts files) in it at the same time seems to works fine, and it’s easier than rewrite the path every time.

  • Another way I found out to debug the typescript code is using the *.ts instead of .js files in the launch.json:outFiles. Why? I don’t know, but it works. From what I have understood, here you are supposed o put the paths to the .js files generated by the transpiler. But when I do that, it debugs the .js files, not the original .ts ones. I.e., breakpoints or stepping through works only with the generated .js files, and setting a breakpoint in the .ts file will show a grayed out circle instead of a full red one indicating it’s not working. But listing the .ts files in the outFiles instead makes the debug to work the original input files in Typescript. If you know why, please tell me! As it works I’m just sticking with it :laughing:.

{
	"version": "0.2.0",
	"configurations": [
		{
			"type": "pwa-node",
			"request": "launch",
			"name": "n8n: build & start",
			"preLaunchTask": "build all",
			"cwd": "${workspaceFolder}/n8n",
			"program": "${workspaceFolder}/n8n/packages/cli/bin/n8n",
			"skipFiles": [ "<node_internals>/**" ],
			"outFiles": [
				"${workspaceFolder}/n8n/packages/**/*.ts",
				"${workspaceFolder}/n8n-nodes-*/**/*.ts",
				"!**/node_modules/**"
			],
			"env": { "EXECUTIONS_PROCESS": "main" },
		},

		{
			"type": "pwa-node",
			"request": "launch",
			"name": "n8n: start",
			"cwd": "${workspaceFolder}/n8n",
			"program": "${workspaceFolder}/n8n/packages/cli/bin/n8n",
			"skipFiles": [ "<node_internals>/**" ],
			"outFiles": [
				"${workspaceFolder}/n8n/packages/**/*.ts",
				"${workspaceFolder}/n8n-nodes-*/**/*.ts",
				"!**/node_modules/**"
			],
			"env": {
				"EXECUTIONS_PROCESS": "main",
			},
		},

		{
			"type": "node-terminal",
			"request": "launch",
			"name": "n8n: dev",
			"command": "npm run dev",
			"cwd": "${workspaceFolder}/n8n",
			"skipFiles": [ "<node_internals>/**" ],
			"outFiles": [
				"${workspaceFolder}/n8n/packages/**/*.ts",
				"${workspaceFolder}/n8n-nodes-*/**/*.ts",
				"!**/node_modules/**"
			],
			"env": { "EXECUTIONS_PROCESS": "main" },
		}
	],
}

I hope this may be helpful for someone passing by what I did, so I’m sharing it here. I may update it as I go, if I find more gotchas. Also, everything that I wrote here is in the public domain (CC0) and can be copied and shared freely.

3 Likes