{"record":{"id":"ed2c2edb15b7be4e","repo":"siyuan-note/siyuan","slug":"stable-release-version-is-invalid","errorCode":null,"errorMessage":"stable release version is invalid","messagePattern":"stable release version is invalid","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/updater_release.go","lineNumber":100,"sourceCode":"\tchannel := Conf.System.UpdateChannel\n\tif conf.UpdateChannelStable == channel {\n\t\treturn getStableUpdateRelease(force)\n\t}\n\tif !isValidUpdateChannel(channel) {\n\t\treturn nil, errors.New(\"update channel is invalid\")\n\t}\n\treturn getGitHubUpdateRelease(channel, force)\n}\n\nfunc getStableUpdateRelease(force bool) (*updateRelease, error) {\n\tresult, err := util.GetRhyResult(context.TODO(), force)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tversion, ok := result[\"ver\"].(string)\n\tnormalizedVersion := normalizeReleaseVersion(version)\n\tif !ok || !semver.IsValid(normalizedVersion) || \"\" != semver.Prerelease(normalizedVersion) {\n\t\treturn nil, errors.New(\"stable release version is invalid\")\n\t}\n\tversion = strings.TrimPrefix(normalizedVersion, \"v\")\n\n\trelease := &updateRelease{\n\t\tVersion:    version,\n\t\tReleaseURL: getStableReleaseURL(result, version),\n\t\tPackages:   map[string]*updatePackage{},\n\t}\n\tpkgName := currentInstallPackageName(release.Version)\n\tif \"\" == pkgName {\n\t\treturn release, nil\n\t}\n\tchecksum := getStablePackageChecksum(result, pkgName)\n\tif \"\" == checksum {\n\t\treturn release, nil\n\t}\n\trelease.Packages[pkgName] = &updatePackage{\n\t\tURLs:     getStablePackageURLs(release.Version, pkgName),","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/updater_release.go#L82-L118","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"result, _ := util.GetRhyResult(ctx, false)\nver, ok := result[\"ver\"].(string)\nsemverValid := ok && semver.IsValid(normalizeReleaseVersion(ver)) && \"\" == semver.Prerelease(normalizeReleaseVersion(ver))","typeGuard":"func validStableVer(v any) bool {\n    s, ok := v.(string)\n    n := normalizeReleaseVersion(s)\n    return ok && semver.IsValid(n) && semver.Prerelease(n) == \"\"\n}","tryCatchPattern":"rel, err := getUpdateRelease(force)\nif err != nil {\n    logging.LogWarnf(\"update check failed: %s\", err)\n    // notify UI 'cannot check updates' instead of crashing\n}","preventionTips":["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"],"tags":["update","semver","cloud-metadata"],"backgroundTag":"unexpected-response-shape","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}