juanfont/headscale · critical · errVersionUpgrade

headscale version %s cannot be used with a database last use

Error message

headscale version %s cannot be used with a database last used by %s, upgrading more than one minor version at a time is not supported, please upgrade to the latest v%d.%d.x release first, then to %s, release page: https://github.com/juanfont/headscale/releases: %w

What it means

The version check allows at most ONE minor version upgrade per step; this database was last used by a release more than one minor version older than the running binary. Skipping minors is blocked because migrations are only guaranteed chainable one minor at a time. The sentinel errVersionUpgrade is wrapped, and the message tells you exactly which intermediate version to install first (v<major>.<storedMinor+1>.x).

Source

Thrown at hscontrol/db/versioncheck.go:258

			"headscale version %s cannot be used with a database last used by %s: %w",
			currentVersion, storedVersion, errVersionMajorChange,
		)
	}

	minorDiff := current.Minor - stored.Minor

	switch {
	case minorDiff == 0:
		// Same minor version — patch changes are always fine.
		return nil

	case minorDiff == 1:
		// Single minor version upgrade — allowed.
		return nil

	case minorDiff > 1:
		// Multi-minor upgrade — blocked.
		return fmt.Errorf(
			"headscale version %s cannot be used with a database last used by %s, "+
				"upgrading more than one minor version at a time is not supported, "+
				"please upgrade to the latest v%d.%d.x release first, then to %s, "+
				"release page: https://github.com/juanfont/headscale/releases: %w",
			currentVersion, storedVersion,
			stored.Major, stored.Minor+1,
			current.String(),
			errVersionUpgrade,
		)

	default:
		// minorDiff < 0 — any minor downgrade is blocked.
		return fmt.Errorf(
			"headscale version %s cannot be used with a database last used by %s, "+
				"downgrading to a previous minor version is not supported, "+
				"release page: https://github.com/juanfont/headscale/releases: %w",
			currentVersion, storedVersion,
			errVersionDowngrade,

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Install the latest patch release of the intermediate minor version named in the message (v<major>.<storedMinor+1>.x), start headscale once so it migrates, then repeat stepwise until at the target version.
  2. Get releases from https://github.com/juanfont/headscale/releases as the message instructs.
  3. If the data is disposable, start with a fresh database instead.
  4. Back up the database file / dump before any stepwise migration.
Defensive patterns

Strategy: validation

Validate before calling

// In deployment scripts, gate upgrades to at most one minor per step:
if current.Minor-stored.Minor > 1 {
    return fmt.Errorf("upgrade stepwise: first install v%d.%d.x", stored.Major, stored.Minor+1)
}

Try / catch

if errors.Is(err, errVersionUpgrade) {
    // parse the message's suggested intermediate version, install it,
    // run migrations, then upgrade again — never skip or force
}

Prevention

When it happens

Trigger: Upgrading e.g. from v0.23 directly to v0.26 (minorDiff > 1): the binary starts, reads the stored version, and refuses to migrate. Also happens when a database file from an old install is reused with a much newer binary.

Common situations: Long-lived deployments jumping several releases at once; package managers (apt/brew) pulling the latest version far ahead of the installed one; containers updated many versions past the data volume's version.

Related errors


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/648691be0a4913cc. Report an issue: GitHub.