heygen-com/hyperframes · error · Error
Unknown skill(s): ${unknown.join(", ")}. Available: ${[...ma
Error message
Unknown skill(s): ${unknown.join(", ")}. Available: ${[...manifestNames].sort().join(", ")} What it means
Thrown (or warned) by updateSkills in strict mode when one or more requested skill names are absent from the fetched manifest. 'removed' entries are filtered out first since they are lock-attributed leftovers, not installable skills. The error lists both the unknown names and the full sorted available set so the user can correct the request.
Source
Thrown at packages/cli/src/commands/skills.ts:362
"Canonical skills manifest was malformed — falling back to presence-only mode (an upstream/CDN issue, not your network).",
),
);
}
check = null; // manifest unreachable (offline / rate-limited) — presence mode below
}
if (!check) return updateSkillsOffline(requested, { strict, cwd: opts.cwd });
// "removed" entries are lock-attributed leftovers, not manifest skills —
// they are `skills update`'s prune concern, never an update target.
const manifestSkills = check.skills.filter((s) => s.status !== "removed");
const manifestNames = new Set(manifestSkills.map((s) => s.name));
const unknown = requested.filter((name) => !manifestNames.has(name));
if (unknown.length) {
const message =
`Unknown skill(s): ${unknown.join(", ")}. ` +
`Available: ${[...manifestNames].sort().join(", ")}`;
if (strict) throw new Error(message);
clack.log.warn(c.warn(message));
}
const targets = manifestSkills.filter(
(s) =>
requested.includes(s.name) ||
isCoreSkill(s.name) ||
(opts.refreshInstalled === true && s.status !== "missing"),
);
const toInstall = targets.filter((s) => s.status === "missing" || s.status === "outdated");
const result: UpdateSkillsResult = {
targets: targets.map((s) => s.name),
installed: toInstall.map((s) => s.name),
current: targets.filter((s) => s.status === "current").map((s) => s.name),
unknown,
presenceOnly: false,
};
View on GitHub (pinned to c2996c8626)
Solutions
- Re-read the 'Available:' list in the error and copy the exact skill name
- Refresh the manifest: `npx hyperframes skills update` (online) then retry
- Check the catalog/docs for renames if you upgraded recently
- Pass skill names as plain slugs without flags/special chars
Example fix
// before hyperframes skills update product-video // after hyperframes skills update product-launch-video
Defensive patterns
Strategy: validation
Validate before calling
async function knownSkills(): Promise<Set<string>> {
const check = await checkSkills(/* cwd */);
return new Set(check.skills.filter((s) => s.status !== "removed").map((s) => s.name));
}
const ok = (await knownSkills()).has(requestedName); Try / catch
try {
await updateSkills([name], { strict: true });
} catch (e) {
if (e.message.startsWith("Unknown skill(s):")) {
// parse 'Available:' list, correct name, retry
}
throw e;
} Prevention
- Refresh the manifest before relying on skill names
- Copy skill names verbatim from the catalog/docs
- Treat any 'Unknown skill' in CI as a rename/removal signal
When it happens
Trigger: updateSkills resolves `check` (a manifest), builds manifestNames from skills with status !== 'removed', then filters `requested` against it. Any unmatched name sets `unknown.length > 0`; in strict mode the message is thrown at skills.ts:362.
Common situations: A typo in the skill name; referencing a skill that was renamed/removed in a newer manifest; using a stale locally-cached manifest; an agent passing a guessed skill slug; referring to a skill that only exists in a different source repo.
Related errors
- --context-fields cannot be empty
- Unknown context field${invalid.length === 1 ? "" : "s"}: ${i
- can't check skills freshness (GitHub manifest unreachable) —
- Malformed skills manifest from ${sourceLabel}
- HTTP ${res.status} fetching ${url}
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/274ab9a8b0d891f7.
Report an issue: GitHub.