ReferenceError: exports is not defined in ES module scope

I am trying to run my bot and am presented with the following error
Successfully compiled: 13 files with swc (25.27ms)
Debugger listening on ws://0.0.0.0:9229/db93ad55-46aa-4ed1-be89-f2b2b5cded3b
For help, see: https://nodejs.org/en/docs/inspector
file:///home/demonicpagan/development/nodejs/discordBots/discord-trakt/dist/bot.js:2
Object.defineProperty(exports, "__esModule", {
^

ReferenceError: exports is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and '/home/demonicpagan/development/nodejs/discordBots/discord-trakt/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
at file:///home/demonicpagan/development/nodejs/discordBots/discord-trakt/dist/bot.js:2:23
at ModuleJob.run (node:internal/modules/esm/module_job:217:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)
at async loadESM (node:internal/process/esm_loader:34:7)
at async handleMainPromise (node:internal/modules/run_main:66:12)

Node.js v20.9.0
 ELIFECYCLE  Command failed with exit code 1.
Successfully compiled: 13 files with swc (25.27ms)
Debugger listening on ws://0.0.0.0:9229/db93ad55-46aa-4ed1-be89-f2b2b5cded3b
For help, see: https://nodejs.org/en/docs/inspector
file:///home/demonicpagan/development/nodejs/discordBots/discord-trakt/dist/bot.js:2
Object.defineProperty(exports, "__esModule", {
^

ReferenceError: exports is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and '/home/demonicpagan/development/nodejs/discordBots/discord-trakt/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
at file:///home/demonicpagan/development/nodejs/discordBots/discord-trakt/dist/bot.js:2:23
at ModuleJob.run (node:internal/modules/esm/module_job:217:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)
at async loadESM (node:internal/process/esm_loader:34:7)
at async handleMainPromise (node:internal/modules/run_main:66:12)

Node.js v20.9.0
 ELIFECYCLE  Command failed with exit code 1.
What do I need to do to resolve this? Since there are so many files involved and the length would exceed the Discord limitations, I created a gist with everything I think is needed. https://gist.github.com/dustin-lennon/30bee1b477e4de8dae3459f4fa4c6b96
Gist
ReferenceError: exports is not defined in ES module scope
ReferenceError: exports is not defined in ES module scope - TraktClient.ts
Solution:
so when using pnpm you need to hoist all of @sapphire/* because otherwise TS cannot properly resolve module augmentations. I forgot the exact option but it's one of the hoist pattern options. As for your root cause, it really comes down to how you configured tsconfig. The modern standard is to use node16 for both module and moduleResolution then either use "type": "commonjs" or "type": "module" in your package.json based on whether you respectively want a CJS or ESM runtime. Once that is done and you compile with either exclusively swc (which you seem to use yet you also mention ts-node, they DO NOT work together, also we discussed the downsides of ts-node) or alternatives such as tsc / tsc-watch / tsup....
Jump to solution
6 Replies
Caspian Nightworth
I figured things out. Had a multiple things to change. In my tsconfig.json I added
"ts-node": {
"experimentalSpecifierResolution": "node",
"esm": true
},
"ts-node": {
"experimentalSpecifierResolution": "node",
"esm": true
},
I needed to adjust my call to my TraktClient to using ./TraktClient.js I had a typo in my bot.ts with the first import. It was #/lib/setup when it should have been #lib/setup Locations in my code where I was calling my constants file needed to be adjusted to resolve errors. well... I thought things were fixed Updating my Gist with my latest changes and I'm currently getting the following error Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@sapphire/pieces' imported from /home/node/dist/lib/constants.js resolved by adding @sapphire/pieces to my package.json. was weird how it worked in one environment but not another without that there
Favna
Favna11mo ago
Are you using pnpm by any chance @Demonic Pagan ? Also regarding ts-node:
Spinel
Spinel11mo ago
TL;DR: Do not use ts-node, use tsc-watch instead. We very strongly discourage using ts-node because it was never meant to be used for bots. ts-node is designed for REPL purposes. That's short for Read Eval Print Loop. Which means to read some code, dump it in an eval() statement, print the result, and loop. A discord bot is not that. A Discord bot sets up a permanent websocket connection to the discord server and connects to the rest gateway. There is read yes, but no eval, no print, and no loop. So what should you use instead? The most ideal way is to just use the watch flag of tsc (tsc --watch) and run node dist/index.js to run your bot, then cancel that process and restart it when you have changes that require restarting. You would open 2 terminal tabs, 1 in which you run tsc --watch and another in which you run the bot. This is in particular the most ideal way, because Discord has a limit to the amount of times you can login with your bot, or register commands, per day. Constantly logging in over and over again due to an auto-restarting process will get you close to that limit very quickly and once you exceed it, your development will be halted entirely for the current day. However, this can be quite tedious so a great package to use instead is tsc-watch.
Caspian Nightworth
yes, i am in regards to ts-node would I replace that in my tsconfig.json with tsc-watch? i probably should stop trying to run the bot in a docker container since it doesn't really make a bit of difference since i'm already developing in a linux environment
Favna
Favna11mo ago
Remove it from tsconfig and just use tsc-watch for dev and tsc for prod build. Correct your main property to dist/whatever and done
Solution
Favna
Favna11mo ago
so when using pnpm you need to hoist all of @sapphire/* because otherwise TS cannot properly resolve module augmentations. I forgot the exact option but it's one of the hoist pattern options. As for your root cause, it really comes down to how you configured tsconfig. The modern standard is to use node16 for both module and moduleResolution then either use "type": "commonjs" or "type": "module" in your package.json based on whether you respectively want a CJS or ESM runtime. Once that is done and you compile with either exclusively swc (which you seem to use yet you also mention ts-node, they DO NOT work together, also we discussed the downsides of ts-node) or alternatives such as tsc / tsc-watch / tsup. The error in particular suggests that you compiled for CJS but are running as ESM (i.e. you specified "type": "module" in your package.json) which causes the error of exports not being defined in an ES module (ESM) scope. So either change your compilation to ESM, or change "type": "module" to "type": "commonjs.
Want results from more Discord servers?
Add your server