siyuan-note/siyuan · error
update channel is invalid
Error message
update channel is invalid
What it means
Returned by getUpdateRelease(force) when Conf.System.UpdateChannel is neither UpdateChannelStable nor a value accepted by isValidUpdateChannel. This is the read-path counterpart to error 940: it guards every release lookup. Unlike SetUpdateChannel (which is user-driven), this fires when the in-memory config holds a corrupted channel string.
Source
Thrown at kernel/model/updater_release.go:87
Digest string `json:"digest"`
State string `json:"state"`
}
var (
cachedGitHubReleases []*githubRelease
githubReleasesCacheTime int64
githubReleasesLock sync.RWMutex
githubReleasesFlight singleflight.Group
githubManifestCache sync.Map
)
func getUpdateRelease(force bool) (*updateRelease, error) {
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,View on GitHub (pinned to 251596fc0d)
Solutions
- Reset the channel via the settings UI or by calling SetUpdateChannel(conf.UpdateChannelStable).
- Fix the conf.json file in the workspace so system.updateChannel is exactly "stable", "beta", or "alpha".
- Call loadGlobalUpdateChannel() to fall back to the per-user ~/.config/siyuan/update.json, which self-heals invalid values to stable (see lines 50-52).
Defensive patterns
Strategy: validation
Validate before calling
// Validate the in-memory channel before any release lookup.
if !isValidUpdateChannel(Conf.System.UpdateChannel) {
Conf.System.UpdateChannel = conf.UpdateChannelStable // self-heal
} Try / catch
// Fall back to stable on the read path.
release, err := getUpdateRelease(false)
if err != nil && strings.Contains(err.Error(), "update channel is invalid") {
Conf.System.UpdateChannel = conf.UpdateChannelStable
release, err = getUpdateRelease(false)
} Prevention
- Never assign Conf.System.UpdateChannel directly — always go through SetUpdateChannel.
- On boot, sanitize the field with isValidUpdateChannel and reset to stable if bad.
- Avoid hand-editing conf.json for the channel; use the settings UI.
When it happens
Trigger: Conf.System.UpdateChannel was set to an invalid value by direct struct mutation bypassing SetUpdateChannel. A config file (conf.json) was hand-edited with a bad channel and loaded at boot. A future code path assigns the channel without validation.
Common situations: Manually editing the workspace conf.json and misspelling the channel. A plugin writes to Conf.System directly. Migration/upgrade code that populated the field incorrectly.
Related errors
- update channel is invalid
- unsupported server type: %s
- command is required for stdio server
- icon [%s] not exists or not available
- theme [%s] not exists or not available for light mode
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/259560d9496f1f75.
Report an issue: GitHub.