mihomo-party-org/clash-party · error · Error
Invalid latest.yml from update source
Error message
Invalid latest.yml from update source
What it means
checkUpdate (src/main/resolve/autoUpdater.ts:112) downloads latest.yml as text and parses it with YAML parse into IAppVersion. Error pages from proxies can still parse as a YAML object (e.g. `404: Not Found`), so the code validates that the result exists and latest.version is a string before compareVersions (which would crash on undefined.replace). Anything failing this shape check throws 'Invalid latest.yml from update source'.
Source
Thrown at src/main/resolve/autoUpdater.ts:112
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')
}
const currentVersion = app.getVersion()
if (compareVersions(latest.version, currentVersion) > 0) {
return latest
} else {
return undefined
}
}
// 1:新 -1:旧 0:相同
function compareVersions(a: string, b: string): number {
const parsePart = (part: string) => {
const numPart = part.split('-')[0]
const num = parseInt(numPart, 10)
return isNaN(num) ? 0 : num
}
const v1 = a.replace(/^v/, '').split('.').map(parsePart)
const v2 = b.replace(/^v/, '').split('.').map(parsePart)View on GitHub (pinned to 911e090537)
Solutions
- Check/clear the githubProxy setting so latest.yml is fetched from a reachable, correct source
- Open the latest.yml URL in a browser and confirm it returns YAML containing `version: x.y.z`
- If 404, verify the release/tag still exists on the update source
- Retry later if the proxy is rate-limiting or temporarily serving error pages
- Ensure compareVersions-like consumers always run after this validation (already enforced by the throw)
Example fix
// before
const latest = parse(res.data as string) as IAppVersion
compareVersions(latest.version, currentVersion) // crashes on '404: Not Found' page
// after
const latest = parse(res.data as string) as IAppVersion
if (!latest || typeof latest.version !== 'string') {
throw new Error('Invalid latest.yml from update source')
} Defensive patterns
Strategy: validation
Validate before calling
const text = res.data as string
const latest = parse(text) as IAppVersion
if (!latest || typeof latest.version !== 'string') {
throw new Error('Invalid latest.yml from update source')
} Type guard
function isValidAppVersion(v: unknown): v is IAppVersion {
return !!v && typeof v === 'object' && typeof (v as IAppVersion).version === 'string'
} Try / catch
try {
const latest = await checkUpdate()
if (latest) promptUpdate(latest)
} catch (e) {
if (e instanceof Error && e.message === 'Invalid latest.yml from update source') {
// proxy served an error page; skip this cycle or retry with another source
console.warn('update check skipped:', e.message)
}
} Prevention
- Validate parsed YAML shape (version is a string) before any string operations like compareVersions
- Check what the latest.yml URL actually returns through configured proxies; error pages parse as YAML too
- Clear/replace a githubProxy that serves HTML or rate-limit pages instead of release files
- Run update checks with graceful failure — a bad source should skip the cycle, not crash the app
When it happens
Trigger: The latest.yml endpoint returns an error page (404/403 HTML or text like `404: Not Found`) that YAML-parses into an object without a string `version` field; the response is empty, or valid YAML whose top level has no version key.
Common situations: A proxy mirror (githubProxy) serves its own error/rate-limit page instead of latest.yml; the release was deleted so latest.yml 404s; a captive portal or firewall injects an HTML block page; the update source URL is misconfigured to a non-GitHub host.
Related errors
- Request failed with status ${res.status}: ${url}
- Subscription failed: Profile missing proxies or providers
- Plugin URL must use a public host
- Profile is not a YAML mapping
- Direct remote profile fetch failed id=${id} url=${redactSubs
AI-assisted analysis of mihomo-party-org/clash-party@911e090537 (2026-08-30).
Data as JSON: /api/errors/6d47c8f49b3ed9ea.
Report an issue: GitHub.