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
- Retry the update check with force=true later, or check https://release.liuyun.io / the Rhy endpoint manually to see what 'ver' currently returns
- Verify network path (VPN/proxy/captive portal) is not mangling the cloud JSON response
- If the cloud is publishing a prerelease or bad version, wait for the maintainers to fix the metadata; the kernel cannot compare it
- 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
- Check cloud endpoint availability before diagnosing locally
- Retry later or with force=true; the error is usually transient cloud metadata corruption
- Verify the raw Rhy JSON has a valid non-prerelease 'ver' before filing a bug
- Avoid proxies that rewrite JSON responses
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
- checksum manifest digest mismatch
- failed to terminate residual kernel processes [ports=" +…
- marketplace package update is not allowed
- marketplace package update not found
- the update install package returned by the kernel is invalid
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)