siyuan-note/siyuan · error

stable release version is invalid

Error message

stable release version is invalid

What it means

getStableUpdateRelease fetches the cloud metadata (Rhy result) and extracts the 'ver' field as the latest stable version. The version must be present, parse as valid semver after normalization, and carry no prerelease suffix. If the cloud returns a missing, non-string, malformed, or prerelease version, this error is thrown because a safe stable-release comparison is impossible.

Solutions

  1. Retry the update check with force=true later, or check https://release.liuyun.io / the Rhy endpoint manually to see what 'ver' currently returns
  2. Verify network path (VPN/proxy/captive portal) is not mangling the cloud JSON response
  3. If the cloud is publishing a prerelease or bad version, wait for the maintainers to fix the metadata; the kernel cannot compare it
  4. As a workaround, switch to a GitHub-backed update channel or download the installer manually from the release page
Defensive patterns

Strategy: retry

Validate before calling

result, _ := util.GetRhyResult(ctx, false)
ver, ok := result["ver"].(string)
semverValid := ok && semver.IsValid(normalizeReleaseVersion(ver)) && "" == semver.Prerelease(normalizeReleaseVersion(ver))

Type guard

func validStableVer(v any) bool {
    s, ok := v.(string)
    n := normalizeReleaseVersion(s)
    return ok && semver.IsValid(n) && semver.Prerelease(n) == ""
}

Try / catch

rel, err := getUpdateRelease(force)
if err != nil {
    logging.LogWarnf("update check failed: %s", err)
    // notify UI 'cannot check updates' instead of crashing
}

Prevention

When it happens

Trigger: CheckUpdate/getUpdatePkg on the stable channel when util.GetRhyResult returns JSON without a valid 'ver' string, or with a version like 'v3.1.0-beta' or 'abc' that fails semver.IsValid or has a non-empty semver.Prerelease after normalizeReleaseVersion.

Common situations: Cloud endpoint temporarily serving degraded/placeholder metadata; network middleboxes or captive portals returning HTML instead of JSON (field missing); a cloud-side release publish in progress where 'ver' is empty or a prerelease; proxy interception rewriting the response.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/ed2c2edb15b7be4e. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/updater_release.go:100

	channel := Conf.System.UpdateChannel
	if conf.UpdateChannelStable == channel {
		return getStableUpdateRelease(force)
	}
	if !isValidUpdateChannel(channel) {
		return nil, errors.New("update channel is invalid")
	}
	return getGitHubUpdateRelease(channel, force)
}

func getStableUpdateRelease(force bool) (*updateRelease, error) {
	result, err := util.GetRhyResult(context.TODO(), force)
	if err != nil {
		return nil, err
	}
	version, ok := result["ver"].(string)
	normalizedVersion := normalizeReleaseVersion(version)
	if !ok || !semver.IsValid(normalizedVersion) || "" != semver.Prerelease(normalizedVersion) {
		return nil, errors.New("stable release version is invalid")
	}
	version = strings.TrimPrefix(normalizedVersion, "v")

	release := &updateRelease{
		Version:    version,
		ReleaseURL: getStableReleaseURL(result, version),
		Packages:   map[string]*updatePackage{},
	}
	pkgName := currentInstallPackageName(release.Version)
	if "" == pkgName {
		return release, nil
	}
	checksum := getStablePackageChecksum(result, pkgName)
	if "" == checksum {
		return release, nil
	}
	release.Packages[pkgName] = &updatePackage{
		URLs:     getStablePackageURLs(release.Version, pkgName),

View on GitHub (pinned to 9f775e8a12)