{"record":{"id":"c8f586546bca2712","repo":"iOfficeAI/AionUi","slug":"update-errors-cdnmanifestfailed","errorCode":"update.errors.cdnManifestFailed","errorMessage":"update.errors.cdnManifestFailed","messagePattern":"update\\.errors\\.cdnManifestFailed","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/desktop/src/process/bridge/updateBridge.ts","lineNumber":370,"sourceCode":"\n/**\n * Fetch and parse the authoritative CDN channel manifest for the current\n * platform/arch. Any failure here fails the manual check — the CDN is the\n * single source of truth for \"is there an update\".\n */\nconst fetchCdnManifest = async (): Promise<CdnLatestManifest> => {\n  const url = `${CDN_BASE_URL}/${resolveCdnChannelFile()}`;\n  const controller = new AbortController();\n  const timeoutId = setTimeout(() => controller.abort(), CDN_MANIFEST_TIMEOUT_MS);\n\n  log.info('[manual-update] Checking CDN manifest:', url);\n  try {\n    const res = await fetch(url, {\n      headers: { 'User-Agent': DEFAULT_USER_AGENT },\n      signal: controller.signal,\n    });\n    if (!res.ok) {\n      throw new Error((await getI18n()).t('update.errors.cdnManifestFailed', { status: res.status }));\n    }\n    const manifest = parseCdnManifest(await res.text());\n    if (!manifest) {\n      throw new Error((await getI18n()).t('update.errors.cdnManifestInvalid'));\n    }\n    log.info('[manual-update] CDN manifest resolved:', {\n      url,\n      version: manifest.version,\n      files: manifest.files.length,\n    });\n    return manifest;\n  } catch (err: unknown) {\n    if (err instanceof Error && err.name === 'AbortError') {\n      throw new Error((await getI18n()).t('update.errors.cdnManifestTimeout'), { cause: err });\n    }\n    throw err;\n  } finally {\n    clearTimeout(timeoutId);","sourceCodeStart":352,"sourceCodeEnd":388,"githubUrl":"https://github.com/iOfficeAI/AionUi/blob/711aa0550ee183ea495dc33e2c05c7943b70a60a/packages/desktop/src/process/bridge/updateBridge.ts#L352-L388","documentation":"Thrown by fetchCdnManifest when fetching the CDN update manifest URL returns a non-OK HTTP status. This is the first failure point of the CDN manifest path (before parsing), with the status code interpolated into the message; the request uses a custom User-Agent and an abort timeout.","triggerScenarios":"Calling fetchCdnManifest when the manifest endpoint returns 404 (wrong URL/manifest not published yet), 403 (bucket permissions/WAF), 5xx (CDN error), or when a proxy intercepts the request. The status value tells which.","commonSituations":"Release not yet published to CDN when the client checks (404 race right after tagging); CDN bucket made private; wrong manifest URL after a domain migration; regional CDN node failure; WAF blocking the custom User-Agent.","solutions":["Read the {status}: 404 => manifest missing (wait for release publish or fix URL), 403 => permissions, 5xx => CDN-side","curl -I the manifest URL to confirm reachability and status","Fix the CDN manifest URL if the domain/path changed","Retry shortly after a release — publish propagation can lag","If 403, make the bucket/object public or serve via signed URLs"],"exampleFix":"# before\nmanifestUrl = https://cdn.example.com/old-path/manifest.json  # 404\n# after\nmanifestUrl = https://cdn.example.com/aionui/manifest.json","handlingStrategy":"fallback","validationCode":"const isManifestUrlReachable = async (url: string): Promise<boolean> => {\n  try { const r = await fetch(url, { method: 'HEAD' }); return r.ok; } catch { return false; }\n};\nif (!(await isManifestUrlReachable(manifestUrl))) {\n  // skip CDN path, use GitHub releases fallback\n}","typeGuard":null,"tryCatchPattern":"try {\n  const manifest = await fetchCdnManifest(url);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('cdnManifestFailed')) {\n    const releases = await fetchGitHubReleases(repo); // fallback channel\n  } else throw err;\n}","preventionTips":["Publish the CDN manifest before tagging a release public","Keep bucket objects public or serve signed URLs","Retry shortly after releases; propagation lags","Always implement a GitHub-releases fallback for update checks"],"tags":["cdn","http-status","updater","manifest"],"backgroundTag":"manifest-fetch-failed","analyzedSha":"711aa0550ee183ea495dc33e2c05c7943b70a60a","analyzedAt":"2026-08-28T07:56:06.558Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}