{"record":{"id":"7dcc82f9e110c5b5","repo":"iOfficeAI/AionUi","slug":"update-errors-cdnmanifesttimeout","errorCode":"update.errors.cdnManifestTimeout","errorMessage":"update.errors.cdnManifestTimeout","messagePattern":"update\\.errors\\.cdnManifestTimeout","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/desktop/src/process/bridge/updateBridge.ts","lineNumber":384,"sourceCode":"      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);\n  }\n};\n\ntype ReleaseNotesEnrichment = { body?: string; htmlUrl?: string; name?: string; publishedAt?: string };\n\n/**\n * Best-effort GitHub lookup for the release matching the CDN version. The\n * manual check must work without GitHub (the repo stays the changelog source\n * but may be unreachable), so every failure path resolves to an empty object.\n */\nconst fetchReleaseNotesEnrichment = async (repo: string, version: string): Promise<ReleaseNotesEnrichment> => {\n  try {\n    const releases = await fetchGitHubReleases(repo, GITHUB_NOTES_TIMEOUT_MS);\n    const match = releases.find((rel) => rel && !rel.draft && normalizeTagToSemver(rel.tag_name) === version);","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/iOfficeAI/AionUi/blob/711aa0550ee183ea495dc33e2c05c7943b70a60a/packages/desktop/src/process/bridge/updateBridge.ts#L366-L402","documentation":"Thrown when fetching the CDN update manifest aborts due to the request timeout (AbortController fires, fetch rejects with AbortError). The original abort is wrapped in a user-facing timeout error with `cause` preserved.","triggerScenarios":"fetchCdnManifest's timeout elapses before the CDN responds; the AbortController signal aborts the fetch and err.name === 'AbortError', triggering this rethrow.","commonSituations":"Slow or blocked CDN, corporate proxy/firewall stalling the request, CDN outage, or a timeout value set too aggressively for large manifests on slow links.","solutions":["Retry the update check — transient CDN slowness is the most common cause","Check network/proxy connectivity to the CDN host (curl -m 10 the manifest URL)","Increase the timeout passed to the AbortController in fetchCdnManifest if on slow networks","Verify the CDN is healthy (status page) during widespread failures"],"exampleFix":"// before\nconst timeoutId = setTimeout(() => abortController.abort(), 5_000);\n\n// after\nconst timeoutId = setTimeout(() => abortController.abort(), 15_000);","handlingStrategy":"retry","validationCode":"// Pre-flight reachability check before the manifest flow\nawait Promise.race([fetch(cdnHost, { method: 'HEAD' }), sleep(2000)]).catch(() => { /* mark CDN unreachable, skip update check */ });","typeGuard":null,"tryCatchPattern":"catch (err) {\n  if (err instanceof Error && /timeout/i.test(err.message)) {\n    return retryWithBackoff(() => fetchCdnManifest(url), { retries: 2 });\n  }\n  throw err;\n}","preventionTips":["Set a timeout proportional to expected manifest size","Surface CDN reachability in the update UI so users understand it's network-side","Keep manifests small so timeouts are rare"],"tags":["update","cdn","timeout","abort","network"],"backgroundTag":"request-timeout","analyzedSha":"711aa0550ee183ea495dc33e2c05c7943b70a60a","analyzedAt":"2026-08-28T07:56:06.558Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}