ERROR Invalid Version: 2.1.0 (2026-01-07)
Something read a version string and refused it. The wording (Invalid Version:
followed by the offending string, usually raised as a TypeError) is what a
semver parser in Node says when it is handed text that is not a valid semantic
version. This is a parse failure during startup: no request was made, so it is
not your API key, not a quota, not the network, and not a broken model. It is
also not a corrupted install in the usual sense — every file may be perfectly
intact and the string still fails.
The string is not something you typed
This is the part that sends people in the wrong direction. The natural reading
of “invalid version” is you passed a bad version somewhere — a typo in an
install command, a wrong tag. Look at the rejected text: 2.1.0 (2026-01-07).
Nobody types that into a shell. It is a release label — the human-readable
form you would find at the top of a changelog — that ended up in a field where a
machine expected a strict version.
So the useful question is not “what is the correct version number”. It is
which program produced that string, and which program parsed it. Semver’s
grammar allows three dot-separated numbers, optionally followed by a -
prerelease segment and a + build-metadata segment, and nothing else. A space
and a parenthesised date are valid English and invalid semver. Somewhere, a
label crossed from a display context into a parsing context, and the parser did
its job.
The second consequence is worse and less obvious: this throws before the tool
finishes starting, so the tool’s own repair paths are on the far side of the
crash. You cannot /doctor your way out of a process that dies during
startup, and you cannot ask it to update itself. Whatever you do has to be done
from outside — your package manager, your config files, your editor’s extension
settings.
Is retrying useful?
No. Parsing is deterministic.
The same bytes produce the same exception on every launch. A second run tells you only that the string is stable, which you already knew. Retrying here is the cheapest possible way to waste ten minutes, because each attempt looks like it might be different and never is.
One action is worth doing once, and it is not a retry: launch through a different entry point. Run the binary directly from a plain shell instead of through your editor, a wrapper script, or a version manager shim. That does not repeat the experiment, it changes which program does the parsing — and if one entry point starts and another crashes, you have just located the parser without reading a line of code.
Locating the two ends of the parse
Work outward from the string itself.
Read the full stderr, not the first line. A stack trace that names a semver module tells you the throw is in Node, inside whichever process printed it. If the trace names an editor extension or a wrapper, the tool underneath may be fine.
Does claude --version print? If it prints a clean version and only your
editor or a wrapper errors, the CLI is healthy and the broken parse is in the
thing wrapping it. If the crash happens before any output, the parse is in the
startup path of the process you launched.
Search your own config for the literal string. grep -rn "2026-01-07"
across your project, your CI definitions, your dotfiles and your shell
environment. If the label appears in a file you control — a pinned version, an
environment variable, a package.json field, a plugin manifest — the search
just ended and the fix is a one-line edit. This is the highest-yield test on the
page, and almost nobody runs it first.
If it appears nowhere you control, the string is coming from installed metadata, which means the build itself carries it. Your side of the fix is to change which build is installed; you cannot correct someone else’s packaged metadata in place, and editing files inside an installed package will be undone by the next update.
Check for more than one install. command -v -a claude (where claude on
Windows). When two installs coexist, a wrapper can read one install’s metadata
while your shell runs another — and the version that gets parsed is not the one
you think you are running.
Fixes, matched to what you found
The label is in a file you control — make the value valid semver: three
numeric parts and nothing after them except an optional -prerelease or
+build segment. If the date genuinely has to travel with the version, semver
has a place for it — build metadata after a + — and parsers accept it there.
The grammar is published at semver.org.
The build itself is the source — install a specific version explicitly instead of the channel default, so the process starts and you are unblocked. Then treat the pin as temporary: a pinned install stops moving, and pinning plus an updater that wants to move you is how people end up months behind and surprised. When a later build starts cleanly, unpin. If the updater starts fighting the pin, that noise shows up as an auto-update failure, which is a different page with a different fix.
An editor extension or wrapper is parsing — update or reinstall it so both halves come from the same release, then restart the editor fully. Two independently updating halves of the same product is the most common way a version string gets read by code that was not written against it.
A version manager is in the picture — confirm the node and npm your
shell resolves are the ones the tool was installed under. A shim that switches
runtime versions per directory can hand a different install’s metadata to the
parser depending on where you launched from.
Knowing you actually fixed it
claude --version prints a string that is exactly three dot-separated numbers,
optionally followed by one - or + segment, with no spaces and no
parentheses. Then start a session in a clean shell — no environment overrides,
not from your editor — and let it complete one turn. Do it twice, from two
different directories, because a directory-scoped version manager or a
project-local config is precisely the kind of thing that makes a fix look
complete when it is not.
One more check, later: re-run claude --version after the next update lands.
Version strings only break when they change, so the next change is the next
opportunity, and knowing where to look takes thirty seconds the second time.
What not to do
Do not reinstall Node, wipe your config directory, or clear caches as a
shotgun. The exception hands you the exact string that failed; a tool that tells
you precisely what it choked on deserves a search, not a rebuild. Every minute
spent reinstalling is a minute not spent running grep.
Related failures in this cluster
If the tool starts fine but cannot replace its own files, that is the auto-update failure — a permissions problem, not a parsing one. If the installer never reaches the point of having a version at all, you are looking at a timeout fetching the release channel. All three are install-time failures that arrive looking like tool bugs; the AI coding error triage tool separates them by what had already happened at the moment of failure.