Skip to content

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.

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.