iOfficeAI/OfficeCLI · error · ArgumentException

Unknown skill: {skillName}. Available: {KnownSkillsList()}

Error message

Unknown skill: {skillName}. Available: {KnownSkillsList()}

What it means

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.

Source

Thrown at src/officecli/Core/SkillInstaller.cs:246

    public static HashSet<string> InstallSkill(string skillName)
    {
        return InstallSkillToAll(skillName);
    }

    /// <summary>All known skill aliases, sorted, comma-joined for error messages.</summary>
    public static string KnownSkillsList() => string.Join(", ", SkillMap.Keys.OrderBy(k => k));

    /// <summary>
    /// Return the embedded SKILL.md content for <paramref name="skillName"/> with
    /// no side-effects and no stdout writes. Throws <see cref="ArgumentException"/>
    /// on unknown skill or missing embedded resource. Used by both the CLI
    /// `officecli load_skill &lt;name&gt;` command and the MCP `load_skill` tool —
    /// shared so the two surfaces have identical semantics.
    /// </summary>
    public static string LoadSkillContent(string skillName)
    {
        if (!SkillMap.TryGetValue(skillName, out var folder))
            throw new ArgumentException($"Unknown skill: {skillName}. Available: {KnownSkillsList()}");
        var content = LoadEmbeddedResource($"skills/{folder}/SKILL.md");
        if (content == null)
            throw new ArgumentException($"Embedded SKILL.md not found for '{skillName}'");
        // A SKILL.md is an entry point that defers detail to bundled reference
        // files (reference/*.md, helper scripts, style libraries). Append a
        // manifest so a text-channel caller (MCP / CLI, no skill install) knows
        // those files exist and how to fetch them — otherwise every
        // "see reference/foo" pointer in the body is a dead link.
        return StripSetupSection(content) + BuildReferenceManifest(skillName);
    }

    /// <summary>
    /// Relative paths of every embedded file for a skill except SKILL.md,
    /// sorted. Uses resource names only (no content read) so binary assets are
    /// listed without being mangled.
    /// </summary>
    public static IReadOnlyList<string> ListSkillFiles(string skillName)
    {

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Read the 'Available:' list in the error message and copy the exact skill name.
  2. Run the skills-listing command to enumerate valid names before invoking load_skill.
  3. Match casing exactly — SkillMap lookup is case-sensitive.

Example fix

// before
officecli load_skill morphppt
// after
officecli load_skill morph-ppt
Defensive patterns

Strategy: validation

Validate before calling

// Validate skill name against the known set before loading
var known = SkillInstaller.KnownSkillsList().Split(", ");
if (!known.Contains(skillName))
    throw new ArgumentException($"Unknown skill '{skillName}'. Known: {SkillInstaller.KnownSkillsList()}");
var content = SkillInstaller.LoadSkillContent(skillName);

Try / catch

try { var content = SkillInstaller.LoadSkillContent(skillName); }
catch (ArgumentException ex) when (ex.Message.StartsWith("Unknown skill"))
{ /* show KnownSkillsList() to the user */ }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13). Data as JSON: /api/errors/3264a343d889f0c4. Report an issue: GitHub.