[Fixed] NPM ERR Unexpected Token '.'
Step by step fixes for the npm ERR! Unexpected token '.' upon build!
Jan 28, 2023 | Read time 9 minutesπ Table of contents
Introduction
Recently, I was building a React application and got this lovely error (on Node 16.14)
npm ERR! Unexpected token '.'
Even when I tried to create a new React application test-app
:
npx create-react-app test-app
Instead of giving the prompts to build a new project, it gave me this error:
npm ERR! Unexpected token '.'
Further output of the error is below:
verbose stack SyntaxError: Unexpected token '.'
verbose stack at Object.compileFunction (node:vm:352:18)
verbose stack at wrapSafe (node:internal/modules/cjs/loader:1026:15)
verbose stack at Module._compile (node:internal/modules/cjs/loader:1061:27)
verbose stack at Object.Module._extensions..js (node:internal/modules/cjs/loader:1149:10)
verbose stack at Module.load (node:internal/modules/cjs/loader:975:32)
verbose stack at Function.Module._load (node:internal/modules/cjs/loader:822:12)
verbose stack at Module.require (node:internal/modules/cjs/loader:999:19)
verbose stack at require (node:internal/modules/cjs/helpers:102:18)
verbose stack at Object. (C:\Program Files\nodejs\node_modules\npm\lib\commands\outdated.js:11:18)
verbose stack at Module._compile (node:internal/modules/cjs/loader:1097:14)
The main reason for this NPM error: NPM ERR Unexpected Token β.β when you are running the build is because of incompatible versions between Node and NPM. There also recently been issues with NVM version 1.1.9!
To fix this issue, we can try to do the following steps:
- Upgrade NVM, Node and NPM versions
- Update the symlinks
- Remove
node_modules
andpackage-lock.json
, and start from scratch. - Downgrade to a previous version of NPM, Node, and NVM to when it was still working
Usually when you get this error during NPM installs or build commands, its mainly due to a bug or incompatible versions. We can try the following:
1. Upgrade NVM, Node and NPM versions
Firstly, check your NPM and node versions:
npm --version
node --version
If we can see that the NPM and Node versions are out of date, we can proceed to the following steps:
- Uninstall
nvm
and reinstall. You can also use chocolatey to do the install instead of relying on the .exe!
For windows, we can go to the binary and install NVM located here:
https://github.com/coreybutler/nvm-windows/tags
For linux distros we can do the following:
sudo apt install curl
curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
source ~/.profile
nvm install node
- Uninstall all versions of node with the following command:
nvm uninstall <node version>
- Reinstall needed node version:
nvm install <node version>
- Use node version just installed:
nvm use <node version>
2. Update the symlinks
One of the reason why this error is popping up is due to the way symbolic links are created within NVM under Windows environments!
Symbolic links are just files that point to the real file (sort of like shortcuts).
With Windows, these symbolic links are incorrectly created as hard files that can be read instead of traversed!
As an example, consider this file thats being created:
nodejs/node_modules/npm/node_modules/@npmcli/arborist
which has contents of ../../workspace/arborist
,
It really should of been a symbolic link to a folder: instead nodejs/node_modules/npm/node_modules/workspace/arborist
.
So when we run our NPM CLI, its says βthere is an unexpected token β.'β - it is trying to read the file as a .js file instead of a symoblic link!
If you find yourself not being able to upgrade to the latest versions of NVM, Node or NPM (usually the case) with working behind coorporate firewalls, you can use this script to clean up your symbolic links:
const fs = require('fs');
const path = require('path');
function exploreFolder(folder) {
const content = fs.readdirSync(folder, { withFileTypes: true });
content.forEach(s => {
const target = path.join(folder, s.name);
if (s.isDirectory()) { return exploreFolder(target); }
if (!s.isFile()) { return; }
const stats = fs.statSync(target);
if (stats.size > 1000) { return; }
checkFile(target);
});
}
function checkFile(file) {
file = fs.realpathSync(file);
const data = fs.readFileSync(file).toString('utf8');
if (!data.startsWith('..')) { return; }
const target = fs.realpathSync(path.join(path.dirname(file), data));
const stats = fs.statSync(target);
fs.rmSync(file);
fs.symlinkSync(target, file, stats.isDirectory() ? 'dir' : 'file');
console.log(target + ' <===> ' + file);
}
function main() {
const node_exe = fs.realpathSync(process.argv[0]);
if (!node_exe) {
console.error('[ERROR]: node executable path not found');
return 1;
}
const node_root = fs.realpathSync(path.dirname(node_exe));
exploreFolder(node_root);
console.log('DONE');
}
process.exit(main());
Save the above code in your root folder as clean_up_script.js or something you prefer.
Then go to your root folder and run: node clean_up_script.js
The code recursively goes through your global node files files/ folders and clean up any incorrect symlinks.
After running the script you can use npm i -g npm@latest to restore the correct node environment (correctly resolving the packages instead of creating symbolic links to them)
The idea is to read the file, and if the file starts with two dots (..
), then it is a incorrect symlink!
The key line to check if a file is a symlink is through the .startsWith("..")
:
const data = fs.readFileSync(file).toString('utf8');
if (!data.startsWith('..')) { return; }
What are symlinks?
For Linux distros, symlinks (symbolic links) are just files that point or link to another file or directory on your system. If you are using Windows, you can think of them similar to shortcuts on the file system.
Usually this is helpful when you have a program that requires your files to be at certain directory. As an example, lets say we have application that requires you to have a C:\Work directory.
Now if you donβt want to use the C:\Work directory, but use a D:\Work directory, we can use symlinks! To do so, we can do the following (given that we are on Windows):
- Move all our required files to the D:\Work directory.
- Go to the C:\Work directory and create a symlink with
mklink /J D:\Work C:\Work
- Now when we open up our program and the program sees that there is a symlink, Windows will redirect it to D:\Work
3. Remove node_modules
and package-lock.json
, and start from scratch.
If the above steps did not work for you, we can try the scorched earth approach - removing everything (node_modules and package-lock.json) and reinstall using npm install
Tip: Careful when deleting package-lock.json
Keep in mind deleting package-lock.json has its own challenges - it could work well with 1 level of dependencies, but with dependencies thats more than 2 levels deep it could get messy. package-lock.json is there for stability and consider carefully before deleting this!
Just make sure you have a backup safely tucked away somewhere :)
- Firstly, open up the terminal and go to the root of your project directory
Tip: Try clear NPM cache
We can try running
npm cache clear --force
to clear the NPM cache. If this does not work - proceed to step 2
- We need to delete the /node_modules with the following command (you might need to use
sudo
before each command):
rm -rf node_modules
- Delete package-lock.json file using the rm command:
rm -rf package-lock.json
- Install the dependencies using the following command:
npm install
4. Downgrade to a previous version of NPM, Node, and NVM to when it was still working
Summary
Getting the error NPM ERR Unexpected Token β.β can be confusing when you first saw it. The error is mainly caused by incompatibilities between Node and NPM.
To get around this error, we can use NVM to manage our Node versions. We just need to install NVM (using chocolatey or binaries), update Node to the latest LTS version and update NPM to the latest version as well.
An additional reason why this error comes up is because of a NVM bug. Updating to the latest NVM version (as of writing it is 1.1.10), this bug should of been fixed.
Lastly if all of the above options do not work, we can try the scorched earth approach - blow everything away (node_modules, package-lock.json) and reinstall all packages with npm install
The very last resort is to downgrade your NVM, NPM or Node versions to a previous working version (this is usually common in corporate firewalled environments where new versions of software are not allowed)