{"record":{"id":"ee11e69acb273e66","repo":"siyuan-note/siyuan","slug":"update-package-is-unavailable","errorCode":null,"errorMessage":"update package is unavailable","messagePattern":"update package is unavailable","errorType":"exception","errorClass":"errUpdatePackageUnavailable","httpStatus":null,"severity":"error","filePath":"kernel/model/updater.go","lineNumber":59,"sourceCode":"\t\treturn \"\"\n\t}\n\n\tdownloadPkgURLs, checksum, err := getUpdatePkg()\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\n\tpkg := path.Base(downloadPkgURLs[0])\n\tpkgPath := filepath.Join(util.TempDir, \"install\", pkg)\n\tlocalChecksum, _ := sha256Hash(pkgPath)\n\tif checksum != localChecksum {\n\t\treturn \"\"\n\t}\n\treturn pkgPath\n}\n\nvar checkDownloadInstallPkgLock = sync.Mutex{}\nvar errUpdatePackageUnavailable = errors.New(\"update package is unavailable\")\n\nfunc checkDownloadInstallPkg(notifyPackageUnavailable bool) {\n\tdefer logging.Recover()\n\n\tif skipNewVerInstallPkg() {\n\t\treturn\n\t}\n\n\tif !checkDownloadInstallPkgLock.TryLock() {\n\t\treturn\n\t}\n\tdefer checkDownloadInstallPkgLock.Unlock()\n\n\tdownloadPkgURLs, checksum, err := getUpdatePkg()\n\tif err != nil {\n\t\tif notifyPackageUnavailable && errors.Is(err, errUpdatePackageUnavailable) {\n\t\t\tif release, releaseErr := getUpdateRelease(false); nil == releaseErr && !isVersionUpToDate(release.Version) {\n\t\t\t\tpushNewVersionNotification(release)","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/updater.go#L41-L77","documentation":"This is the sentinel error declaration `var errUpdatePackageUnavailable = errors.New(\"update package is unavailable\")` at updater.go:59. It is the base of an error family: getUpdatePkg() wraps it with fmt.Errorf(\"%w ...\", errUpdatePackageUnavailable) to add platform/package context. Callers detect any member of this family with errors.Is(err, errUpdatePackageUnavailable), which checkDownloadInstallPkg uses to decide whether to push a 'new version available but no package' notification.","triggerScenarios":"The sentinel itself is never returned bare by getUpdatePkg; it is wrapped at lines 119, 124, and 128. It surfaces to callers via errors.Is. It is matched in checkDownloadInstallPkg (line 75) to trigger pushNewVersionNotification when a newer release exists but the current platform has no installable artifact.","commonSituations":"Running SiYuan on Linux (no .exe/.dmg package produced), on an unsupported architecture (e.g. 386), or when a freshly published release has not yet uploaded all platform assets. The user sees a 'new version available' banner but the auto-download never starts.","solutions":["Detect the family with errors.Is(err, model.errUpdatePackageUnavailable) rather than string matching, since the wrapped message varies by platform and package.","If on Linux, install updates via your package manager instead of the in-app updater — the updater only ships Windows (.exe) and macOS (.dmg) artifacts.","If on Windows/macOS, wait for the release to finish uploading all assets, then retry; the release is published before all binaries are attached."],"exampleFix":"// before\nif err.Error() == \"update package is unavailable\" { ... } // fragile, never matches wrapped forms\n\n// after\nif errors.Is(err, errUpdatePackageUnavailable) {\n    pushNewVersionNotification(release)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// In checkDownloadInstallPkg-style callers, distinguish 'no package' from real failures.\n_, _, err := getUpdatePkg()\nif err != nil {\n    if errors.Is(err, errUpdatePackageUnavailable) && notifyPackageUnavailable {\n        if release, rerr := getUpdateRelease(false); rerr == nil && !isVersionUpToDate(release.Version) {\n            pushNewVersionNotification(release) // tell user a new version exists, just no auto-pkg\n        }\n    }\n    return // not a hard failure\n}","preventionTips":["Always use errors.Is(err, errUpdatePackageUnavailable) — never string-match the wrapped message.","Treat the family as 'soft': notify the user rather than failing the whole update flow.","On Linux or unsupported arch, disable the in-app download UI so users aren't promised a package that can't arrive."],"tags":["update","platform","package","sentinel-error"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}