{"record":{"id":"1d04466bca991957","repo":"can1357/oh-my-pi","slug":"github-release-asset-binaryname-has-an-unsuppor","errorCode":null,"errorMessage":"GitHub release asset ${binaryName} has an unsupported digest","messagePattern":"GitHub release asset (.+?) has an unsupported digest","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/cli/update-cli.ts","lineNumber":229,"sourceCode":"\n\tconst matches = release.assets.filter(asset => isRecord(asset) && asset.name === binaryName);\n\tif (matches.length !== 1) {\n\t\tthrow new Error(`GitHub release ${expectedTag} has ${matches.length} assets named ${binaryName}`);\n\t}\n\n\tconst asset = matches[0];\n\tif (!isRecord(asset) || asset.state !== \"uploaded\") {\n\t\tthrow new Error(`GitHub release asset ${binaryName} is not fully uploaded`);\n\t}\n\tif (typeof asset.size !== \"number\" || !Number.isSafeInteger(asset.size) || asset.size <= 0) {\n\t\tthrow new Error(`GitHub release asset ${binaryName} has an invalid size`);\n\t}\n\tif (typeof asset.digest !== \"string\") {\n\t\tthrow new Error(`GitHub release asset ${binaryName} has no digest`);\n\t}\n\tconst digest = /^sha256:([0-9a-f]{64})$/i.exec(asset.digest)?.[1];\n\tif (!digest) {\n\t\tthrow new Error(`GitHub release asset ${binaryName} has an unsupported digest`);\n\t}\n\n\tconst expectedUrl = `https://github.com/${REPO}/releases/download/${expectedTag}/${binaryName}`;\n\tif (asset.browser_download_url !== expectedUrl) {\n\t\tthrow new Error(`GitHub release asset ${binaryName} has an unexpected download URL`);\n\t}\n\n\treturn {\n\t\turl: expectedUrl,\n\t\tsize: asset.size,\n\t\tdigest: `sha256:${digest.toLowerCase()}`,\n\t};\n}\n\nasync function getReleaseBinaryAsset(\n\texpectedVersion: string,\n\tbinaryName: string,\n\tfetchImpl: Fetch = fetch,","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/cli/update-cli.ts#L211-L247","documentation":"GitHub reports asset digests as `sha256:<64 hex chars>`. The updater parses this strict format and rejects any digest that is present but does not match — e.g. a different algorithm prefix, wrong length, or non-hex characters — because it cannot be used for the sha256 verification the installer performs.","triggerScenarios":"resolveReleaseBinaryAsset throws when the regex `/^sha256:([0-9a-f]{64})$/i` fails to match the asset's digest string.","commonSituations":"GitHub changing or introducing a new digest algorithm prefix (e.g. sha512), locally re-uploaded assets carrying nonstandard digests, a stub/mocked digest like \"abc\" in tests, or a proxy corrupting the value.","solutions":["Inspect the asset's digest field via the API; if it is genuinely non-sha256, GitHub's format changed — update the regex and digest handling in update-cli.ts.","Re-upload the asset so GitHub regenerates a standard sha256 digest.","Fix test stubs to use a valid \"sha256:\" + 64 hex chars value.","Ensure no proxy is rewriting the JSON body."],"exampleFix":"// before (invalid stub digest)\ndigest: \"md5:d41d8cd98f00b204e9800998ecf8427e\"\n// after\ndigest: \"sha256:\" + \"b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9\"","handlingStrategy":"type-guard","validationCode":"const asset = release.assets?.find(a => a?.name === binaryName);\nif (typeof asset?.digest === \"string\" && !/^sha256:[0-9a-f]{64}$/i.test(asset.digest)) {\n  throw new Error(`Unsupported digest format: ${asset.digest}`);\n}","typeGuard":"function hasSha256Digest(asset: unknown): asset is { digest: string } {\n  return typeof (asset as { digest?: unknown })?.digest === \"string\"\n    && /^sha256:[0-9a-f]{64}$/i.test((asset as { digest: string }).digest);\n}","tryCatchPattern":"try {\n  await update();\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"has an unsupported digest\")) {\n    console.error(\"Asset digest is not sha256:<64 hex>; GitHub format may have changed. Update the client.\");\n  } else throw err;\n}","preventionTips":["Use strict regex validation on checksum strings before using them.","Watch GitHub changelogs for digest-format changes.","In test stubs, generate digests as \"sha256:\" + 64 hex chars."],"tags":["github-api","checksum","update","integrity"],"backgroundTag":"unsupported-checksum-format","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}