{"record":{"id":"928a2eb0315861cb","repo":"CloakHQ/CloakBrowser","slug":"cloakbrowser-using-cached-license-validation-se","errorCode":null,"errorMessage":"[cloakbrowser] Using cached license validation (server unreachable)","messagePattern":"\\[cloakbrowser\\] Using cached license validation \\(server unreachable\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"js/src/license.ts","lineNumber":519,"sourceCode":"    const info: LicenseInfo = {\n      valid: Boolean(data.valid ?? false),\n      plan: String(data.plan ?? \"solo\"),\n      expires: data.expires != null ? String(data.expires) : null,\n    };\n\n    if (info.valid) {\n      writeCache(cachePath, keySha, info);\n    }\n    return info;\n  } catch (e) {\n    console.warn(\n      `[cloakbrowser] License validation request failed: ${e instanceof Error ? e.message : e}`\n    );\n\n    // Fall back to stale cache\n    const stale = readCache(cachePath, keySha, true);\n    if (stale) {\n      console.warn(\"[cloakbrowser] Using cached license validation (server unreachable)\");\n      return stale;\n    }\n\n    return null;\n  }\n}\n\n/** Get the server-resolved Pro release and channel for this platform. */\nexport async function getProLatestRelease(releaseChannel?: string): Promise<ProReleaseInfo | null> {\n  const channel = normalizeReleaseChannel(releaseChannel);\n  const markerSuffix = channel === \"preview\"\n    ? `preview_${getPlatformTag()}`\n    : getPlatformTag();\n  const marker = path.join(getCacheDir(), `.last_pro_version_check_${markerSuffix}`);\n  const resolutionMarker = path.join(\n    getCacheDir(),\n    `.last_pro_version_resolution_${markerSuffix}`,\n  );","sourceCodeStart":501,"sourceCodeEnd":537,"githubUrl":"https://github.com/CloakHQ/CloakBrowser/blob/d6bad5de261bedf025280ace1d14e800aee13923/js/src/license.ts#L501-L537","documentation":"This is a console.warn, not a thrown error: license validation could not reach the validation server (network failure, DNS, timeout, or server outage), so the library falls back to the last cached validation result. It exists so offline usage still works while signaling that freshness could not be guaranteed. If no stale cache exists, validateLicense returns null and the caller sees a normal license failure.","triggerScenarios":"Calling validateLicense() (directly or via launch, which validates the license) while the machine has no internet, a firewall blocks the license endpoint, DNS fails, or the license server is down — and a previous successful validation was cached on disk.","commonSituations":"CI runners without network access, corporate proxies blocking the endpoint, temporary server outages, expired-cache TTL after long offline periods. If the cache is expired/missing the same network condition produces a hard license failure instead.","solutions":["Restore network connectivity or fix proxy/firewall rules so the license server is reachable, then re-run to refresh the cache.","If running in CI/offline by design, perform one online validation to populate the cache before going offline.","Delete the stale cache file (path from cachePath) to force a fresh validation once back online, confirming the cached license is still valid.","Check for a license-server status page or library update if the outage persists."],"exampleFix":"// before: launch offline, relies on stale cache\nawait cloakbrowser.launchPersistentContext('./profile');\n\n// after: validate online once, cache refreshed, warning gone\nconst result = await cloakbrowser.validateLicense();\nif (!result) throw new Error('license invalid');\nawait cloakbrowser.launchPersistentContext('./profile');","handlingStrategy":"retry","validationCode":"// probe connectivity before launching\nimport { setTimeout as sleep } from 'timers/promises';\nasync function isLicenseServerReachable(): Promise<boolean> {\n  try {\n    const res = await fetch('https://license.cloakbrowser.example/health', {\n      signal: AbortSignal.timeout(5000),\n    });\n    return res.ok;\n  } catch { return false; }\n}\nconst online = await isLicenseServerReachable();\nif (!online) console.warn('expect stale-cache license validation');","typeGuard":null,"tryCatchPattern":"// validateLicense returns null rather than throwing on network failure — treat null as fatal\nconst result = await cloakbrowser.validateLicense();\nif (!result) throw new Error('No license and no cached validation available');","preventionTips":["Run one online validation (e.g. in CI warm-up) to keep the disk cache fresh before offline jobs.","Monitor egress firewall/proxy rules for the license endpoint.","Treat any return of null from validateLicense as 'license unusable', not merely 'offline'."],"tags":["network","license","cache","offline"],"backgroundTag":"server-unreachable","analyzedSha":"d6bad5de261bedf025280ace1d14e800aee13923","analyzedAt":"2026-08-28T14:13:12.918Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}