{"record":{"id":"14084f97549061fd","repo":"laurent22/joplin","slug":"could-not-check-for-updates-please-try-again-late","errorCode":null,"errorMessage":"Could not check for updates. Please try again later (Error ${status}).","messagePattern":"Could not check for updates\\. Please try again later \\(Error (.+?)\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/app-desktop/utils/checkForUpdatesUtils.ts","lineNumber":148,"sourceCode":"\t}\n\n\tconst output: Release = {\n\t\tversion: version,\n\t\tdownloadUrl: downloadUrl,\n\t\tnotes: cleanUpReleaseNotes(fullReleaseNotes),\n\t\tpageUrl: release.html_url,\n\t\tprerelease: release.prerelease,\n\t};\n\n\treturn output;\n};\n\nexport const handleReleaseResponseError = (status: number, responseText: string): never => {\n\tif ((status === 403 || status === 429) && responseText.toLowerCase().includes('rate limit')) {\n\t\tthrow new Error('Could not check for updates. The server rate limit has been exceeded — this is a temporary issue, please try again later.');\n\t}\n\n\tthrow new Error(`Could not check for updates. Please try again later (Error ${status}).`);\n};\n","sourceCodeStart":130,"sourceCodeEnd":150,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/app-desktop/utils/checkForUpdatesUtils.ts#L130-L150","documentation":"Thrown by handleReleaseResponseError as the catch-all when the GitHub releases API returns any HTTP error status that is not a recognized rate-limit (403/429 without 'rate limit' in the body, or any other 4xx/5xx). The status code is interpolated into the message.","triggerScenarios":"checkForUpdates receives a non-2xx response (e.g. 404 if the release endpoint moved, 500/502/503 server errors, 401 auth errors) that does not match the rate-limit condition; handleReleaseResponseError throws with the raw status.","commonSituations":"GitHub is temporarily unavailable (5xx); a corporate proxy intercepts and returns a non-200; the configured release URL points to a repo with no releases (404); DNS/network failure surfacing as a captured status; plugin-based updaters pointing at a wrong endpoint.","solutions":["Retry after a short wait — transient 5xx errors self-resolve.","Check network connectivity and proxy configuration (HTTPS_PROXY / corporate TLS inspection).","Verify the release feed URL is correct and the target repo has published releases.","If persistent, inspect the raw response body logged upstream to diagnose the specific status."],"exampleFix":"// before\nthrow new Error(`Could not check for updates. Please try again later (Error ${status}).`);\n\n// after — surface responseText excerpt for diagnosis\nthrow new Error(`Could not check for updates (HTTP ${status}). Server said: ${responseText.slice(0, 120)}`);","handlingStrategy":"retry","validationCode":"const status = await fetchReleaseStatus();\nif (status >= 500) {\n  // server error — retry with backoff\n  await backoffRetry(() => checkForUpdates());\n} else if (status >= 400) {\n  // client/config error — do not retry blindly\n}","typeGuard":"function isTransientError(status: number): boolean {\n  return status === 408 || status === 425 || status === 500 || status === 502 || status === 503 || status === 504;\n}","tryCatchPattern":"try {\n  await checkForUpdates();\n} catch (e) {\n  const match = e.message.match(/Error (\\d+)/);\n  const status = match ? Number(match[1]) : 0;\n  if (isTransientError(status)) {\n    // retry with exponential backoff\n  } else {\n    // surface to user / log responseText\n  }\n}","preventionTips":["Retry 5xx errors with exponential backoff; do not retry 4xx (except 429).","Log the raw responseText alongside the status for diagnosis.","Verify the release-feed URL and proxy settings if errors persist."],"tags":["desktop","updates","network","http-error","github"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}