{"record":{"id":"3264a343d889f0c4","repo":"iOfficeAI/OfficeCLI","slug":"unknown-skill-skillname-available-knownskill","errorCode":null,"errorMessage":"Unknown skill: {skillName}. Available: {KnownSkillsList()}","messagePattern":"Unknown skill: (.+?)\\. Available: (.+?)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/SkillInstaller.cs","lineNumber":246,"sourceCode":"    public static HashSet<string> InstallSkill(string skillName)\n    {\n        return InstallSkillToAll(skillName);\n    }\n\n    /// <summary>All known skill aliases, sorted, comma-joined for error messages.</summary>\n    public static string KnownSkillsList() => string.Join(\", \", SkillMap.Keys.OrderBy(k => k));\n\n    /// <summary>\n    /// Return the embedded SKILL.md content for <paramref name=\"skillName\"/> with\n    /// no side-effects and no stdout writes. Throws <see cref=\"ArgumentException\"/>\n    /// on unknown skill or missing embedded resource. Used by both the CLI\n    /// `officecli load_skill &lt;name&gt;` command and the MCP `load_skill` tool —\n    /// shared so the two surfaces have identical semantics.\n    /// </summary>\n    public static string LoadSkillContent(string skillName)\n    {\n        if (!SkillMap.TryGetValue(skillName, out var folder))\n            throw new ArgumentException($\"Unknown skill: {skillName}. Available: {KnownSkillsList()}\");\n        var content = LoadEmbeddedResource($\"skills/{folder}/SKILL.md\");\n        if (content == null)\n            throw new ArgumentException($\"Embedded SKILL.md not found for '{skillName}'\");\n        // A SKILL.md is an entry point that defers detail to bundled reference\n        // files (reference/*.md, helper scripts, style libraries). Append a\n        // manifest so a text-channel caller (MCP / CLI, no skill install) knows\n        // those files exist and how to fetch them — otherwise every\n        // \"see reference/foo\" pointer in the body is a dead link.\n        return StripSetupSection(content) + BuildReferenceManifest(skillName);\n    }\n\n    /// <summary>\n    /// Relative paths of every embedded file for a skill except SKILL.md,\n    /// sorted. Uses resource names only (no content read) so binary assets are\n    /// listed without being mangled.\n    /// </summary>\n    public static IReadOnlyList<string> ListSkillFiles(string skillName)\n    {","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/SkillInstaller.cs#L228-L264","documentation":"Thrown by LoadSkillContent when skillName is not a key in SkillMap. The message lists all known skills (KnownSkillsList, sorted) so the caller can correct the name. Shared by the CLI 'officecli load_skill <name>' command and the MCP load_skill tool, so both surfaces throw identically. ArgumentException.","triggerScenarios":"Calling officecli load_skill <name> or the MCP load_skill tool with a name absent from SkillMap — a typo, a removed skill, or a name from an older version.","commonSituations":"Misspelling a skill name, using a casing the map does not honor (the map is case-sensitive), referencing a skill after an upgrade that renamed/removed it, or guessing a name instead of listing available skills first.","solutions":["Read the 'Available:' list in the error message and copy the exact skill name.","Run the skills-listing command to enumerate valid names before invoking load_skill.","Match casing exactly — SkillMap lookup is case-sensitive."],"exampleFix":"// before\nofficecli load_skill morphppt\n// after\nofficecli load_skill morph-ppt","handlingStrategy":"validation","validationCode":"// Validate skill name against the known set before loading\nvar known = SkillInstaller.KnownSkillsList().Split(\", \");\nif (!known.Contains(skillName))\n    throw new ArgumentException($\"Unknown skill '{skillName}'. Known: {SkillInstaller.KnownSkillsList()}\");\nvar content = SkillInstaller.LoadSkillContent(skillName);","typeGuard":null,"tryCatchPattern":"try { var content = SkillInstaller.LoadSkillContent(skillName); }\ncatch (ArgumentException ex) when (ex.Message.StartsWith(\"Unknown skill\"))\n{ /* show KnownSkillsList() to the user */ }","preventionTips":["Always list skills first when unsure of the exact name.","Match casing exactly — SkillMap is case-sensitive.","Re-check names after upgrading officecli, which may rename skills."],"tags":["skills","argument","validation","cli"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}