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

  1. Verify the GitHub Release assets actually include a `digest` field of form sha256:<64 hex> (curl the release API for the tag)
  2. Ensure the `file` name passed in exactly matches the release asset name (case-sensitive)
  3. Update to a release published after GitHub added digest support, or republish the release assets so GitHub generates digests
  4. 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

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


AI-assisted analysis of mihomo-party-org/clash-party@911e090537 (2026-08-30). Data as JSON: /api/errors/25506d111b9e0a9d. Report an issue: GitHub.