{"record":{"id":"704a622530ed5041","repo":"heygen-com/hyperframes","slug":"can-t-check-skills-freshness-github-manifest-unre","errorCode":null,"errorMessage":"can't check skills freshness (GitHub manifest unreachable) — refusing to report success. Retry when online.","messagePattern":"can't check skills freshness \\(GitHub manifest unreachable\\) — refusing to report success\\. Retry when online\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/skills.ts","lineNumber":441,"sourceCode":" * still succeed.\n *\n *   - Named run (`update <workflow>`): presence-check requested + fallback\n *     core, blind-install whatever is absent (a truly dead network fails the\n *     clone fast, and `strict` decides how loudly). Stale-but-present\n *     proceeds — blocking a build on a network hiccup is worse than running\n *     one release behind.\n *   - Bare run (nothing requested): the whole job was freshness, and presence\n *     can't prove it. strict — the documented `check || update` CI contract —\n *     must fail loudly rather than exit 0 while everything stays stale.\n *     Non-strict (init) still presence-checks the fallback core, so a fresh\n *     machine gets a best-effort core install instead of nothing.\n */\nasync function updateSkillsOffline(\n  requested: readonly string[],\n  opts: { strict: boolean; cwd?: string },\n): Promise<UpdateSkillsResult> {\n  if (requested.length === 0 && opts.strict) {\n    throw new Error(\n      \"can't check skills freshness (GitHub manifest unreachable) — refusing to report success. Retry when online.\",\n    );\n  }\n\n  const targets = [...new Set([...requested, ...FALLBACK_CORE_SKILLS])];\n  const present = new Set(presentSkills(targets, { cwd: opts.cwd }));\n  const absent = targets.filter((name) => !present.has(name));\n\n  console.log(\n    c.dim(\n      absent.length === 0\n        ? \"Skills freshness check unavailable (offline?) — installed skills found, continuing without a refresh.\"\n        : `Skills freshness check unavailable (offline?) — attempting a blind install of: ${absent.join(\", \")}`,\n    ),\n  );\n\n  if (absent.length > 0) {\n    await installSkills(absent, { cwd: opts.cwd, strict: opts.strict });","sourceCodeStart":423,"sourceCodeEnd":459,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/skills.ts#L423-L459","documentation":"Thrown by updateSkillsOffline in strict mode when nothing was requested and the GitHub manifest is unreachable. Offline, freshness is unknowable; a bare strict run (the documented `skills check || skills update` CI contract) must fail loudly rather than exit 0 while everything stays stale. Non-strict runs still presence-check the fallback core set and proceed.","triggerScenarios":"updateSkillsOffline(requested, {strict:true}) with requested.length === 0 throws immediately at skills.ts:441. Reach updateSkillsOffline when the manifest fetch failed (raw.githubusercontent.com blocked, no network).","commonSituations":"CI running `hyperframes skills check` behind a corporate proxy that blocks raw.githubusercontent.com; offline dev machine; GitHub outage; DNS failure. Any context where the manifest can't be fetched AND the run is strict AND no specific skill was requested.","solutions":["Restore network access to raw.githubusercontent.com and retry","If you must run offline, pass an explicit skill name so presence-checking kicks in instead of the strict freshness contract","Run non-strict (init) which degrades gracefully to presence-checking the fallback core","Configure proxy/allowlist for raw.githubusercontent.com in CI"],"exampleFix":"// before (CI, offline, fails)\nhyperframes skills check\n// after (online)\nhyperframes skills check\n// or scope to a skill so presence is checked\nhyperframes skills update pr-to-video","handlingStrategy":"try-catch","validationCode":"async function canReachManifest(): Promise<boolean> {\n  try {\n    await fetch(\"https://raw.githubusercontent.com/\");\n    return true;\n  } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await updateSkills([], { strict: true });\n} catch (e) {\n  if (e.message.includes(\"manifest unreachable\")) {\n    // degrade: pass an explicit skill, or run non-strict\n  }\n  throw e;\n}","preventionTips":["Allowlist raw.githubusercontent.com in corporate proxies/CI","Scope strict CI checks to online runs","Pass explicit skill names so offline runs presence-check instead of asserting freshness"],"tags":["skills","network","offline","ci","manifest"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}