iOfficeAI/AionUi · error · Error
update.errors.cdnManifestInvalid
update.errors.cdnManifestInvalid
Error message
update.errors.cdnManifestInvalid
What it means
Thrown when the CDN update manifest was fetched successfully (HTTP 200) but failed to parse via parseCdnManifest. This means the response body is not valid manifest JSON or is missing required fields (version, files). It indicates the CDN is serving an unexpected/corrupted payload.
Source
Thrown at packages/desktop/src/process/bridge/updateBridge.ts:374
* single source of truth for "is there an update".
*/
const fetchCdnManifest = async (): Promise<CdnLatestManifest> => {
const url = `${CDN_BASE_URL}/${resolveCdnChannelFile()}`;
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), CDN_MANIFEST_TIMEOUT_MS);
log.info('[manual-update] Checking CDN manifest:', url);
try {
const res = await fetch(url, {
headers: { 'User-Agent': DEFAULT_USER_AGENT },
signal: controller.signal,
});
if (!res.ok) {
throw new Error((await getI18n()).t('update.errors.cdnManifestFailed', { status: res.status }));
}
const manifest = parseCdnManifest(await res.text());
if (!manifest) {
throw new Error((await getI18n()).t('update.errors.cdnManifestInvalid'));
}
log.info('[manual-update] CDN manifest resolved:', {
url,
version: manifest.version,
files: manifest.files.length,
});
return manifest;
} catch (err: unknown) {
if (err instanceof Error && err.name === 'AbortError') {
throw new Error((await getI18n()).t('update.errors.cdnManifestTimeout'), { cause: err });
}
throw err;
} finally {
clearTimeout(timeoutId);
}
};
type ReleaseNotesEnrichment = { body?: string; htmlUrl?: string; name?: string; publishedAt?: string };View on GitHub (pinned to 711aa0550e)
Solutions
- Open the resolved CDN manifest URL in a browser/curl and verify it returns valid JSON with `version` and `files`
- Check the CDN deployment pipeline for truncated or failed uploads of the manifest
- Verify the manifest URL construction in updateBridge.ts (correct base URL, channel and platform path)
- Make parseCdnManifest failures log the raw body excerpt so future diagnosis is easier
Example fix
// before
const manifest = parseCdnManifest(await res.text());
// after (diagnose what the CDN actually returned)
const text = await res.text();
const manifest = parseCdnManifest(text);
if (!manifest) {
log.error('[manual-update] CDN manifest unparsable, first 200 chars:', text.slice(0, 200));
throw new Error((await getI18n()).t('update.errors.cdnManifestInvalid'));
} Defensive patterns
Strategy: validation
Validate before calling
const res = await fetch(url);
const text = await res.text();
try {
const parsed = JSON.parse(text);
if (typeof parsed.version !== 'string' || !Array.isArray(parsed.files)) {
// reject before calling parseCdnManifest-dependent flows
}
} catch { /* not JSON */ } Type guard
type CdnManifest = { version: string; files: Array<{ path: string }> };
function isCdnManifest(v: unknown): v is CdnManifest {
if (typeof v !== 'object' || v === null) return false;
const o = v as Record<string, unknown>;
return typeof o.version === 'string' && Array.isArray(o.files);
} Try / catch
catch (err) { log.error('[update] manifest invalid', { url, bodySnippet }); throw err; } Prevention
- Contract-test the manifest schema on every CDN deploy
- Log unparsable manifest bodies (truncated) for fast diagnosis
- Fail CDN deploys that would publish a manifest without version/files
When it happens
Trigger: Calling the update manifest flow where the CDN URL returns 200 with HTML (error page), a JSON object missing `version` or `files`, or malformed JSON that parseCdnManifest rejects.
Common situations: CDN misconfiguration serving an index.html fallback, a partially uploaded/truncated manifest file, wrong CDN base URL pointing at a directory listing, or a manifest schema change after an update.
Related errors
- update.errors.cdnManifestFailed
- update.errors.cdnManifestTimeout
- update.errors.downloadFailed
- update.errors.downloadNoBody
AI-assisted analysis of iOfficeAI/AionUi@711aa0550e (2026-08-28).
Data as JSON: /api/errors/4afaf0aef02885f0.
Report an issue: GitHub.