/commands/nodejs/check-syntax-without-running
node --check file.js: check JavaScript syntax without running it
- tool
- Node.js
- versions
- Node.js 10+
- os
- any
node --check app.js (short form node -c app.js) parses the file and reports syntax errors without executing it. It prints nothing and exits with code 0 when the syntax is valid, and prints the error with the line number and exits with code 1 when it is not. It is a cheap gate for CI jobs, Git hooks and deployment scripts that must not start a broken file.
Check a valid and a broken file
printf 'const sum = (a, b) => a + b;\nconsole.log(sum(1, 2));\n' > ok.js
printf 'function broken( {\n return 1;\n}\n' > broken.js
node --check ok.js && echo "ok.js: syntax OK"
node --check broken.js 2>&1 | grep -E "^SyntaxError|broken.js:"
echo "exit code: ${PIPESTATUS[0]}"Output
ok.js: syntax OK /tmp/work/broken.js:2 SyntaxError: Unexpected number exit code: 1
The valid file is parsed but not run, so its console.log never prints. For the broken file Node.js prints the file and line, the offending source line with a caret, then the SyntaxError message, and exits with 1.
What it does and does not catch
| Problem | Caught by node --check |
|---|---|
| Missing bracket, parenthesis or quote | Yes |
| Invalid keyword use (top-level await in CommonJS, return at the top level of an ES module) | Yes |
| import/export in a file marked as CommonJS | Yes: Cannot use import statement outside a module |
| Undefined variable or function | No, it is only a run-time ReferenceError |
| Missing module in require or import | No, modules are not resolved |
| TypeScript files | No: type annotations are reported as syntax errors; use tsc --noEmit |
The module type follows the usual rules: a .mjs file, or a .js file under a package.json with "type": "module", is parsed as an ES module, and a .cjs file or a "type": "commonjs" package as CommonJS. A .js file with no type set goes through Node.js syntax detection, so top-level await or import passes there; the same file fails under "type": "commonjs".
Useful variants
| Command | What it does |
|---|---|
| node -c app.js | Short form of --check |
| node --check app.mjs | Checks the file as an ES module |
| find src -name '*.js' -print0 | xargs -0 -n1 node --check | Checks every .js file, one node process each |
| git diff --cached --name-only -- "*.js" | xargs -n1 node --check | Pre-commit hook: only the staged JavaScript files |
| echo 'let x = 1' | node --check | Checks code read from standard input |
Pitfalls
node --checkchecks one file: innode --check a.js b.jsonlya.jsis parsed, andb.jsis treated as an argument to the script. Loop over files instead.- It does not apply type stripping:
node --check app.tsreports the first type annotation as aSyntaxErroreven on Node.js versions that runnode app.ts. - A file that passes can still fail when it runs, so keep tests and a linter in the pipeline. Use
--checkas the fast first step, not as the only one.
How to confirm it worked
Check the exit code: node --check app.js; echo $? prints 0 for valid syntax and 1 for a syntax error. In a shell script, node --check app.js || exit 1 stops the script on the first broken file. The meaning of other exit codes is listed in Node.js exit codes.
FAQ
Does node --check find undefined variables or wrong imports?
No. It only parses the file. A call to a function that does not exist, a misspelt variable or an import of a missing module is valid syntax and passes; only running the code or a linter such as ESLint finds those.
How do I check every file in a folder?
node --check takes one file per run, so loop over them, for example find src -name '*.js' -print0 | xargs -0 -n1 node --check. xargs checks every file and exits with code 123 if any of them failed, which fails a CI step.
Can node --check validate JSON?
Not as a JSON file. Parse it instead with node -e "JSON.parse(require('fs').readFileSync('data.json','utf8'))", which exits non-zero and prints the position of the first error.