siyuan-note/siyuan · error
checksum manifest digest mismatch
Error message
checksum manifest digest mismatch
What it means
During a SiYuan auto-update check, getGitHubManifestChecksum downloads the SHA256 checksum manifest for a GitHub release and, when a trusted manifest digest (hash of the manifest itself) is supplied, compares it against the SHA256 of the downloaded bytes. A mismatch means the manifest bytes were altered in transit or served by something other than the expected release — a supply-chain integrity guard. The update is aborted rather than verifying package checksums against a possibly forged manifest.
Solutions
- Retry the update check — a transiently corrupted or interrupted download is the most common cause; the next fetch re-downloads and re-verifies
- Disable or bypass HTTP proxies/interceptors for GitHub (unset HTTP_PROXY/HTTPS_PROXY or allowlist github.com) so the manifest is fetched unmodified
- Check SiYuan version: if the release was re-published upstream, wait for a new release rather than accepting the stale manifest
- Verify network integrity (DNS hijack / MITM); compare the manifest downloaded manually (sha256sum) against the digest in the release metadata
- If it persists on every attempt with a stock build, report it on siyuan-note/siyuan — the published metadata and manifest are out of sync
Example fix
// no code fix on the caller side; network-side fix // before (proxied) HTTPS_PROXY=http://corp-proxy:8080 ./siyuan // after (bypass proxy for GitHub) NO_PROXY=github.com,objects.githubusercontent.com ./siyuan
Defensive patterns
Strategy: retry
Try / catch
// Go caller of the update check
if checksum, err := getGitHubUpdateRelease(ctx); err != nil {
if strings.Contains(err.Error(), "digest mismatch") {
log.Warn("manifest digest mismatch; likely proxy/CDN tampering, retrying without proxy")
// retry after disabling proxy / after backoff
}
} Prevention
- Allowlist github.com in proxy/SSL-interception settings so release assets pass unmodified
- Retry update checks with backoff before treating a mismatch as fatal
- Verify manual sha256 of the manifest when mismatches recur to distinguish transient corruption from tampering
When it happens
Trigger: Calling getGitHubUpdateRelease (update check against GitHub releases) where the release metadata supplies a manifestDigest but the bytes fetched from manifestAsset.BrowserDownloadURL hash to a different SHA256 — e.g. a proxy/mirror returning rewritten content, a cached/stale CDN response, or a re-uploaded manifest without updated metadata.
Common situations: Corporate or national proxies (GitHub accessed via mirror) serving modified manifests; GitHub release assets replaced after metadata was generated; transparent TLS interception; flaky download truncated/extended then re-hashed differently; running an unofficial build whose expected digest drifted from the published manifest.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- access to private/internal IP is prohibited
- access to private/internal IP is prohibited
- AI editor request timeout
- AI editor stream idle timeout
- authentication probe returned HTTP " + response.status
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/344113c0769d3f40.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/updater_release.go:404
}
if nil == response || nil == response.Response {
return "", errors.New("checksum manifest response is empty")
}
defer response.Body.Close()
if 200 != response.StatusCode {
return "", fmt.Errorf("get checksum manifest failed: %d", response.StatusCode)
}
data, err := io.ReadAll(io.LimitReader(response.Body, maxChecksumManifestSize+1))
if err != nil {
return "", err
}
if maxChecksumManifestSize < int64(len(data)) {
return "", errors.New("checksum manifest is too large")
}
if "" != manifestDigest {
actualDigest := fmt.Sprintf("%x", sha256.Sum256(data))
if manifestDigest != actualDigest {
return "", errors.New("checksum manifest digest mismatch")
}
}
manifest := string(data)
if "" != manifestCacheKey {
githubManifestCache.Store(manifestCacheKey, manifest)
}
checksum := parseChecksumManifest(manifest, pkgName)
if "" == checksum {
return "", errors.New("package checksum is unavailable")
}
return checksum, nil
}
func parseChecksumManifest(manifest, pkgName string) string {
for _, line := range strings.Split(manifest, "\n") {
fields := strings.Fields(line)
if 2 > len(fields) {
continueView on GitHub (pinned to 9f775e8a12)