Fix print "%s.%s.%s" invalid syntax in yarn install
Find the old node-gyp hiding in your lockfile, see why pointing it at Python 3 or Python 2 no longer works, and get yarn install green again with Dart Sass.
TL;DR#
The line import sys; print "%s.%s.%s" % sys.version_info[:3]; is not your code. It is the Python version probe of node-gyp 3.8.0, written in Python 2 syntax. Python 3 rejects a print statement without parentheses, so the probe crashes before node-gyp compiles anything, and yarn install fails on the package that asked for the native build, usually node-sass 4.x. Node-gyp releases since v8.0.0 no longer support Python 2 at all, and a current base image such as Debian 12 no longer packages it, so the durable fix is to get node-gyp 3 out of the tree: replace node-sass with sass (Dart Sass), or, if you must keep it for now, move to the node-sass release that matches your Node version.
The error, as posted in the Stack Overflow question (36 votes, no accepted answer), from a MacBook Pro M1 Max running Node 14.18.1 from Homebrew:
error */node_modules/node-sass: Command failed.
Exit code: 1
Command: node scripts/build.js
...
gyp info using node-gyp@3.8.0
gyp info using node@14.18.1 | darwin | arm64
gyp verb check python checking for Python executable "/opt/homebrew/opt/python@3.9/bin/python3" in the PATH
gyp verb `which` succeeded /opt/homebrew/opt/python@3.9/bin/python3 /opt/homebrew/opt/python@3.9/bin/python3
gyp ERR! configure error
gyp ERR! stack Error: Command failed: /opt/homebrew/opt/python@3.9/bin/python3 -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack File "<string>", line 1
gyp ERR! stack import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack ^
gyp ERR! stack SyntaxError: invalid syntaxThe question is from 2021, but the same line keeps arriving in recent bug reports: a node-sass Docker build in June 2025, a headless-gl install on macOS Tahoe in January 2026, and an Arch Linux install on Node 22 in February 2026. The headless-gl and Arch logs both name node-gyp 3.8.0, and all three print the same Python 2 line.
Why node-gyp 3.8.0 crashes on Python 3#
The node-sass install first tries to download a prebuilt binding for your platform and Node version. When none exists, it falls back to node scripts/build.js, which runs node-gyp rebuild. Installing node-sass 4.14.1 on Node 20 in the reproduction below showed that fallback:
Downloading binary from https://github.com/sass/node-sass/releases/download/v4.14.1/linux-x64-115_binding.node
Cannot download "https://github.com/sass/node-sass/releases/download/v4.14.1/linux-x64-115_binding.node":
HTTP error 404 Not Found
Building: /usr/local/bin/node /work/t/node_modules/node-gyp/bin/node-gyp.js rebuild --verbose --libsass_ext= --libsass_cflags= --libsass_ldflags= --libsass_library=The question's log shows the same Command: node scripts/build.js, then rebuild cleaning and moving on to configure, which must find Python before it can run gyp.
In node-gyp 3.8.0, lib/configure.js picks the interpreter in this order: the --python option, then the PYTHON environment variable, then python2 on the PATH, then python. Whatever it finds, it then runs this check (line 451 of that file):
var args = ['-c', 'import sys; print "%s.%s.%s" % sys.version_info[:3];']That one-liner is valid Python 2 and invalid Python 3. A few lines further down, the same function only accepts a version in the range >=2.5.0 <3.0.0, so even a probe that ran would have rejected Python 3. Node-gyp 3.x was simply built for Python 2.
Support arrived later. The node-gyp CHANGELOG records "accept Python 3 after Python 2" in v5.0.5, "accept Python 3 by default" in v6.0.0, and, in v8.0.0, "remove support for Python 2". The current node-gyp README goes further and warns that Python 3.12 and later require node-gyp 10 or newer.
The old node-gyp usually arrives through node-sass. On the npm registry, node-sass 4.14.1 depends on node-gyp ^3.8.0, while node-sass 5.0.0 moved to ^7.1.0 and node-sass 7.0.3 to ^8.4.1. So whenever node-sass 4 finds no prebuilt binding, as on Node 20, it compiles with a node-gyp that cannot run on a machine where python means Python 3. The headless-gl report shows the same node-gyp 3.8.0 reached through prebuild instead, so the parent package can differ; the probe is identical.
Reproduce it on Node 20#
The failure was reproduced on 10 October 2026 in a throwaway node:20-bookworm container (Node 20.20.2, yarn 1.22.22, npm 10.8.2, Debian 12.13, Python 3.11.2), with yarn add node-sass@4.14.1 in an empty project.
With no python command on the PATH, node-gyp 3.8.0 fails earlier with a different message, because it looks for python2, then python, and never tries python3:
gyp info using node-gyp@3.8.0
gyp info using node@20.20.2 | linux | x64
gyp ERR! configure error
gyp ERR! stack Error: Can't find Python executable "python", you can set the PYTHON env variable.Installing Debian's python-is-python3 package, so that python points to Python 3 (the Arch report hit the error through /usr/bin/python in the same way), turns that into the error from the question:
gyp verb check python checking for Python executable "python" in the PATH
gyp verb `which` succeeded python /usr/bin/python
gyp ERR! configure error
gyp ERR! stack Error: Command failed: /usr/bin/python -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack File "<string>", line 1
gyp ERR! stack import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
gyp ERR! stack SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?The last line differs from the question: the Python 3.9 in the question printed SyntaxError: invalid syntax, the Python 3.11 in the reproduction prints the "Missing parentheses" hint. It is the same failure, and searching for either wording should bring you here.
Find what pulls node-gyp 3 into your tree#
Before changing anything, confirm which package owns the old node-gyp. Yarn 1 prints the dependency chain in its deprecation warnings during the failing install; in the reproduction it named node-sass directly:
warning node-sass > node-gyp > tar@2.2.2: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.meThe lockfile says the same without running the install scripts. In a Yarn 1 lockfile the entry is keyed by the requested range; in the reproduction, with node-sass 4.14.1 in package.json:
grep -n "node-gyp@" yarn.lock707:node-gyp@^3.8.0:In an npm lockfile the entry is keyed by its path instead, so read its version, or ask npm for the chain once node_modules exists:
node -p "require('./package-lock.json').packages['node_modules/node-gyp'].version"
npm ls node-gyp3.8.0
legacy-app@1.0.0 /work/n
`-- node-sass@4.14.1
`-- node-gyp@3.8.0If the parent is node-sass, follow the fix below. If it is something else, such as prebuild in the headless-gl report, the fix is the same idea: upgrade the parent to a release that depends on a current node-gyp.
Fix: replace node-sass with Dart Sass#
The node-sass README now opens with a warning that the project "has reached end of life" and that projects still using it "should move onto Dart Sass". The repository is archived, and npm marks every release, including the latest 9.0.0, as deprecated: "Node Sass is no longer supported. Please use sass or sass-embedded instead." The sass package describes itself as "A pure JavaScript implementation of Sass", so installing it never calls node-gyp.
- Remove node-sass and add sass:
yarn remove node-sass
yarn add -D sassWith npm, the same change is:
npm uninstall node-sass
npm install --save-dev sass- Point any script that called the
node-sassCLI at thesassCLI instead. The Dart Sass command-line documentation lists its options; the two-argument form takes an input and an output file:
{
"scripts": {
"build:css": "sass src/styles.scss dist/styles.css"
}
}- Run a clean install, so no copy of node-gyp 3 survives in
node_modulesor the lockfile:
rm -rf node_modules
yarn installIn the reproduction, the same empty project took sass 1.105.1 and compiled a small stylesheet with nesting and a variable:
$ /work/app/node_modules/.bin/sass styles.scss styles.css
Done in 0.61s..btn {
color: #0b5fff;
}
.btn:hover {
opacity: 0.8;
}If a bundler loader compiles your Sass rather than a script, check that loader's documentation for how it chooses its Sass implementation before you remove node-sass.
If you cannot leave node-sass today#
The top Stack Overflow answer fixed it by "upping the node-sass version to the correct version based on my Node installation". The node-sass README keeps a support table for that: Node 20 needs node-sass 9.0 or later, Node 18 needs 8.0 or later, and Node 14 is covered by 4.14 up to, but not including, 9.0. In the reproduction, with python still pointing at Python 3, node-sass 9.0.0 installed on Node 20 and loaded. In a separate npm install with no python on the PATH at all, it downloaded a prebuilt binding for that Node version, so node-gyp never ran:
Downloading binary from https://github.com/sass/node-sass/releases/download/v9.0.0/linux-x64-115_binding.node
Download complete
Binary saved to /work/s/node_modules/node-sass/vendor/linux-x64-115/binding.nodenode-sass 9.0.0 (Wrapper) [JavaScript]
libsass 3.5.5 (Sass Compiler) [C/C++]Treat this as a bridge. On a platform without a prebuilt binding, node-sass 9.0.0 compiles with node-gyp ^8.4.1, and the node-gyp README warns that Python 3.12 and later need node-gyp 10 or newer, so such a source build on a newer Python can fail again in a different way.
Workarounds that no longer work#
The second answer on the question recommends installing Python 2 (it uses pyenv on macOS) and saving its path with npm config set python. The reproduction tested both halves on Debian 12 with npm 10, and both failed. A Python 2 built through pyenv was not tested here.
On Debian 12, the base of the official node:20-bookworm image, Python 2 is gone:
E: Package 'python2' has no installation candidateAnd npm 10 refuses the config key:
npm error `python` is not a valid npm optionNode-gyp itself still honours the npm_config_python environment variable and its --python option, as the node-gyp README documents. That helps a current node-gyp pick between several Python 3 installs, but pointing node-gyp 3.8.0 at a Python 3 interpreter is exactly what produces this error. The Homebrew path in the question, /opt/homebrew/opt/python@3.9/bin/python3, is such a case.
Verify the fix#
After the clean install, the old node-gyp must be gone and your styles must compile:
grep -c "node-gyp@^3" yarn.lock
yarn sass src/styles.scss dist/styles.cssThe first command should print 0, as it did in the reproduction after yarn remove node-sass and yarn add -D sass. There, yarn list --pattern node-gyp returned no package at all after the switch to sass, because nothing in the tree needed native compilation any more. Commit the updated lockfile, so CI and Docker builds stop resolving node-sass 4.
One email a month — the latest explained errors
What the site published that month — mostly Next.js, Supabase and Node errors, explained. You confirm by email; unsubscribe any time in one click.
Docker builds and Apple Silicon#
The June 2025 ldwizard report above is a container build, and the reproduction shows why images are a dead end for node-gyp 3.8.0: node:20-bookworm has Python 3 but no python command and no installable Python 2 package. Without python, node-gyp 3.8.0 cannot find an interpreter; with python-is-python3, it runs the Python 2 probe and crashes. Fix the dependency rather than the image. If the build then passes but the container fails at runtime with a permission error under node_modules/.cache, that is a separate problem with who owns node_modules, covered in EACCES: permission denied, mkdir node_modules/.cache.
On a Mac, the question's log shows the build path running on an arm64 Node 14. Once node-gyp is current, a native build on macOS can still stop at the toolchain check; that error is gyp: No Xcode or CLT version detected. If node-sass installs but later complains about a missing binding after a Node upgrade, see Node Sass could not find a binding for your current environment.
If the project also builds with webpack 4, the next stop may be Node's OpenSSL 3. If yarn install now passes but the build on Node 17 or later stops with error:0308010C:digital envelope routines::unsupported, continue with the error:0308010C fix, which explains the MD4 hash behind it and the webpack or react-scripts upgrade that removes it.
The SyntaxError itself is never about your Python install. It is a 2018-era build tool reading a Python 3 interpreter as if it were Python 2, and every fix that lasts removes that tool from the dependency tree instead of trying to feed it the interpreter it expects.
Further reading: require() of ES Module string-width: fix yarn.lock in Docker.
Frequently Asked Questions
Still stuck? Paste your error.
Paste the error message or stack trace — we check it against every fix and tool on the site.
Continue Reading
require() of ES Module string-width: fix yarn.lock in Docker
Why yarn install in a node:18 container dies in node-gyp with ERR_REQUIRE_ESM from wide-align, how to spot the broken yarn.lock entry, and two fixes reproduced in Docker.
Fix ERR spawn EINVAL from npx install-peerdeps on Windows
Why a lint script that adds Airbnb ESLint config with Yarn dies on Windows with ERR spawn EINVAL, the one-word change that makes it run, and what the fixed release does to your version ranges.
Fix gyp: No Xcode or CLT version detected! in npm install
Learn which of the three checks node-gyp runs on macOS is failing, repair the Command Line Tools, and get native modules compiling again.


