mihomo-party-org/clash-party · critical · Error
GitHub Release does not provide a SHA-256 digest for "${file
Error message
GitHub Release does not provide a SHA-256 digest for "${file}" What it means
getGitHubAssetSha256 (src/main/resolve/autoUpdater.ts:94) fetches the GitHub Release metadata and extracts the asset's `digest` field, expecting the format `sha256:<64 hex chars>`. If the digest is absent or malformed (no regex match), it throws because the updater refuses to install a binary whose integrity cannot be verified. Note: GitHub only populates the digest field on newer releases/API responses, so older or third-party-mirrored releases commonly lack it.
Source
Thrown at src/main/resolve/autoUpdater.ts:94
proxy: UpdaterProxy
): Promise<string> {
const releaseTag = encodeURIComponent(`v${version}`)
const res = await chromeRequest.get<GitHubRelease>(
`https://api.github.com/repos/mihomo-party-org/mihomo-party/releases/tags/${releaseTag}`,
{
headers: {
Accept: 'application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28'
},
proxy,
timeout: 5000,
responseType: 'json'
}
)
const digest = res.data.assets?.find((asset) => asset.name === file)?.digest
const match = digest?.match(/^sha256:([a-f\d]{64})$/i)
if (!match) {
throw new Error(`GitHub Release does not provide a SHA-256 digest for "${file}"`)
}
return match[1].toLowerCase()
}
export async function checkUpdate(): Promise<IAppVersion | undefined> {
const [{ 'mixed-port': mixedPort = DEFAULT_MIHOMO_PORTS.mixed }, { githubProxy = '' }] =
await Promise.all([getControledMihomoConfig(), getAppConfig()])
const githubUrl =
'https://github.com/mihomo-party-org/mihomo-party/releases/latest/download/latest.yml'
const res = await tryDownload(buildDownloadUrls(githubUrl, githubProxy), {
headers: { 'Content-Type': 'application/octet-stream' },
proxy: updaterProxy(mixedPort),
responseType: 'text'
})
const latest = parse(res.data as string) as IAppVersion
// 错误页也能被 YAML 解析成对象(如 `404: Not Found`),不校验会让 compareVersions 崩在 undefined.replace
if (!latest || typeof latest.version !== 'string') {
throw new Error('Invalid latest.yml from update source')View on GitHub (pinned to 911e090537)
Solutions
- Verify the GitHub Release assets actually include a `digest` field of form sha256:<64 hex> (curl the release API for the tag)
- Ensure the `file` name passed in exactly matches the release asset name (case-sensitive)
- Update to a release published after GitHub added digest support, or republish the release assets so GitHub generates digests
- If using a proxy for the release API call, fetch metadata directly from api.github.com so the digest field is not stripped
Example fix
// before
getGitHubAssetSha256('AppSetup-0.9.0-old.exe') // release predates digests
// after — verify before calling
const assets = await getReleaseAssets(tag)
if (!assets.find(a => a.digest?.startsWith('sha256:'))) {
throw new Error('release lacks sha256 digest; publish new assets')
} Defensive patterns
Strategy: validation
Validate before calling
const res = await octokit.rest.repos.getReleaseByTag({ owner, repo, tag })
const digest = res.data.assets.find(a => a.name === file)?.digest
const ok = typeof digest === 'string' && /^sha256:[a-f\d]{64}$/i.test(digest)
if (!ok) throw new Error(`asset ${file} lacks sha256 digest; cannot verify`) Type guard
function hasSha256Digest(asset: { name: string; digest?: string }): asset is { name: string; digest: string } {
return /^sha256:[a-f\d]{64}$/i.test(asset.digest ?? '')
} Try / catch
try {
const sha = await getGitHubAssetSha256(file)
} catch (e) {
if (e instanceof Error && e.message.includes('SHA-256 digest')) {
// refuse install; prompt user to republish release or fetch checksum from elsewhere
safeShowErrorBox('updater.integrityUnavailable', e.message)
}
} Prevention
- Only auto-update from releases published after GitHub digest support (mid-2024+); verify via the release API
- Compare asset names exactly (case-sensitive) between latest.yml and release assets
- Fetch release metadata directly from api.github.com rather than through stripping proxies
- Treat missing digests as a hard failure — never install unverifiable binaries (supply-chain guard)
When it happens
Trigger: Calling installUpdate when the GitHub Release for the target file has no digest on the asset, a digest in an unexpected format (not sha256:...), or the JSON response lacks the asset entry (name mismatch between latest.yml file and actual release asset).
Common situations: Old releases published before GitHub added sha256 digests; proxied/mirror sources strip or alter release metadata; asset name in latest.yml does not exactly match the release asset name so find() returns undefined; GitHub API returning partial/cached JSON.
Related errors
- Request failed with status ${res.status}: ${url}
- Invalid latest.yml from update source
- GitHub API error: ${error.message}
- Failed to fetch version list
AI-assisted analysis of mihomo-party-org/clash-party@911e090537 (2026-08-30).
Data as JSON: /api/errors/25506d111b9e0a9d.
Report an issue: GitHub.