{"record":{"id":"8c7f22c3df2887e4","repo":"heygen-com/hyperframes","slug":"skill-s-still-missing-after-install-absent-joi","errorCode":null,"errorMessage":"Skill(s) still missing after install: ${absent.join(\", \")}","messagePattern":"Skill\\(s\\) still missing after install: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/skills.ts","lineNumber":411,"sourceCode":"}\n\n/**\n * The presence half of the guarantee, after an install claims success: every\n * name must now exist on disk. Catches the \"install exited 0 but delivered\n * nothing\" failure mode, which would otherwise surface much later as a\n * workflow reading skill files that aren't there.\n *\n * Strictness mirrors the caller's tolerance: a strict run (the `check ||\n * update` CI contract, the router's trigger-time guarantee) throws so the\n * failure is loud; a non-strict run (init) only warns and proceeds, since a\n * skills hiccup must never break scaffolding.\n */\nfunction verifyInstalled(names: readonly string[], opts: { strict: boolean; cwd?: string }): void {\n  const present = new Set(presentSkills(names, { cwd: opts.cwd }));\n  const absent = names.filter((name) => !present.has(name));\n  if (absent.length === 0) return;\n  const message = `Skill(s) still missing after install: ${absent.join(\", \")}`;\n  if (opts.strict) throw new Error(message);\n  clack.log.warn(c.warn(message));\n}\n\n/**\n * Offline degradation for updateSkills: the manifest is unreachable, so\n * freshness is unknowable. What can still be honored is the PRESENCE half of\n * the guarantee, extended to the pinned FALLBACK_CORE_SKILLS list so the\n * router / preamble promise (\"this workflow plus the core set it depends on\")\n * doesn't silently shrink to just the named skill on degraded networks —\n * raw.githubusercontent.com blocked while `git clone` works is a real\n * corporate-proxy shape, which is exactly when the blind install below can\n * 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.","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/skills.ts#L393-L429","documentation":"Thrown (or warned) by verifyInstalled after an install attempt when some requested skills still aren't on disk. presentSkills is re-evaluated against the names list; any name not present is 'absent'. Strictness mirrors the caller — strict (check/update CI contract, router trigger-time guarantee) throws loud; non-strict (init) only warns and proceeds.","triggerScenarios":"verifyInstalled(names, {strict}) computes present = presentSkills(names) and filters absent names; if absent is non-empty and opts.strict is true the message is thrown at skills.ts:411.","commonSituations":"The `npx skills add` clone/copy step partially failed (network hiccup, disk full); a skill directory was deleted after install; permissions blocked writing the skill files; a manifest pointed at a path that no longer exists in the repo.","solutions":["Re-run the install online: `npx hyperframes skills update <name>`","Check disk space and write permissions in the target .agents/skills dir","Inspect the install log for the failing skill and retry just that one","If non-strict, the warning is non-fatal — proceed or install manually"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"function presentSkills(names: string[], opts: { cwd?: string }): string[] {\n  // returns the subset of `names` whose directories exist under .agents/skills\n  return names.filter((n) => existsSync(join(opts.cwd ?? \".\", \".agents/skills\", n)));\n}","typeGuard":null,"tryCatchPattern":"try {\n  verifyInstalled(names, { strict: true });\n} catch (e) {\n  if (e.message.includes(\"still missing after install\")) {\n    // re-run the install online, then verify again\n  }\n  throw e;\n}","preventionTips":["Run installs online and check disk/permissions beforehand","Re-verify presence after every install before depending on a skill","Don't delete skill directories out from under the CLI"],"tags":["skills","install","filesystem","verification"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}