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

  1. Open the resolved CDN manifest URL in a browser/curl and verify it returns valid JSON with `version` and `files`
  2. Check the CDN deployment pipeline for truncated or failed uploads of the manifest
  3. Verify the manifest URL construction in updateBridge.ts (correct base URL, channel and platform path)
  4. 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

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


AI-assisted analysis of iOfficeAI/AionUi@711aa0550e (2026-08-28). Data as JSON: /api/errors/4afaf0aef02885f0. Report an issue: GitHub.