{"record":{"id":"39b88eebc8a5fd21","repo":"iOfficeAI/OfficeCLI","slug":"plugin-m-name-declares-unsupported-target-m","errorCode":null,"errorMessage":"Plugin '{m.Name}' declares unsupported target '{m.Target}'. Expected one of: docx, xlsx, pptx.","messagePattern":"Plugin '(.+?)' declares unsupported target '(.+?)'\\. Expected one of: docx, xlsx, pptx\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/Plugins/PluginManifest.cs","lineNumber":159,"sourceCode":"            return v;\n        return Default > 0 ? Default : SafeDefault.Default;\n    }\n}\n\npublic static class PluginManifestExtensions\n{\n    /// <summary>\n    /// Canonical target format name (\"docx\"/\"xlsx\"/\"pptx\"). Defaults to\n    /// \"docx\" for plugins that omit the field. Throws if the manifest declares\n    /// an unsupported target.\n    /// </summary>\n    public static string ResolveTargetFormat(this PluginManifest m)\n    {\n        var t = (m.Target ?? \"docx\").ToLowerInvariant();\n        return t switch\n        {\n            \"docx\" or \"xlsx\" or \"pptx\" => t,\n            _ => throw new InvalidOperationException(\n                $\"Plugin '{m.Name}' declares unsupported target '{m.Target}'. Expected one of: docx, xlsx, pptx.\"),\n        };\n    }\n\n    /// <summary>\n    /// File extension (with leading dot) for the plugin's target format.\n    /// </summary>\n    public static string ResolveTargetExtension(this PluginManifest m) =>\n        \".\" + m.ResolveTargetFormat();\n\n    /// <summary>\n    /// Resolve the idle timeout for a verb, applying the safe default when the\n    /// manifest is silent.\n    /// </summary>\n    public static int ResolveIdleTimeout(this PluginManifest m, string verb)\n    {\n        // Environment-variable escape hatch so a user hitting a hung plugin\n        // can bypass the manifest budget without rebuilding the plugin:","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Plugins/PluginManifest.cs#L141-L177","documentation":"Thrown by PluginManifest.ResolveTargetFormat() when the manifest's target field is a non-null value that isn't docx, xlsx, or pptx (case-insensitive). A null target defaults safely to docx, so this only fires when the plugin explicitly declares an unrecognized format. This is an InvalidOperationException, not a CliException — it surfaces during plugin discovery/validation.","triggerScenarios":"Calling PluginManifest.ResolveTargetFormat() or ResolveTargetExtension() on a manifest whose Target property is set to something like 'doc', 'pdf', 'odt', 'PPT', or a typo like 'docxx'. These extension methods are invoked during plugin registry loading, plugins list, and at format-handler invocation time.","commonSituations":"Plugin author sets target to the input format ('doc') instead of the native OOXML target ('docx'). Plugin author uses an abbreviation ('ppt' instead of 'pptx'). Plugin was written for a future format OfficeCLI doesn't support yet. Typo in the manifest JSON. Plugin declares a non-OOXML format like 'pdf' or 'odt' as its target.","solutions":["Set the manifest's target field to one of: docx, xlsx, or pptx (case-insensitive).","Remember: target is the NATIVE OOXML format the plugin produces, not the foreign input format. A .doc → .docx dump-reader should set target to 'docx', not 'doc'.","If the plugin truly needs a target OfficeCLI doesn't support, the target field can be omitted entirely (defaults to 'docx') — but only if docx is correct.","Run `plugins lint` or `plugins list` to validate the manifest before invoking the plugin."],"exampleFix":"// before: manifest declares the foreign input format as target\n{\n  \"name\": \"doc-reader\",\n  \"target\": \"doc\",\n  \"kinds\": [\"dump-reader\"],\n  \"extensions\": [\".doc\"]\n}\n\n// after: target is the native OOXML format the dump replays into\n{\n  \"name\": \"doc-reader\",\n  \"target\": \"docx\",\n  \"kinds\": [\"dump-reader\"],\n  \"extensions\": [\".doc\"]\n}","handlingStrategy":"validation","validationCode":"// Validate the target before calling ResolveTargetFormat\nstatic readonly HashSet<string> ValidTargets = new() { \"docx\", \"xlsx\", \"pptx\" };\n\nvar target = (manifest.Target ?? \"docx\").ToLowerInvariant();\nif (!ValidTargets.Contains(target))\n    throw new ArgumentException($\"Manifest target '{manifest.Target}' is invalid. Use: docx, xlsx, pptx, or omit (defaults to docx).\");\n\n// Safe to call:\nvar format = manifest.ResolveTargetFormat();","typeGuard":"static bool IsValidTargetFormat(PluginManifest m)\n{\n    var t = (m.Target ?? \"docx\").ToLowerInvariant();\n    return t is \"docx\" or \"xlsx\" or \"pptx\";\n}","tryCatchPattern":"try\n{\n    var ext = manifest.ResolveTargetExtension();\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"unsupported target\"))\n{\n    // Manifest has a bad target field. Fix the manifest JSON.\n    Console.Error.WriteLine($\"Plugin '{manifest.Name}' has invalid target '{manifest.Target}'. Use docx/xlsx/pptx.\");\n}","preventionTips":["Run `plugins lint` after editing a manifest to validate all fields.","Remember: target is the native OOXML format (docx/xlsx/pptx), not the foreign input format.","Omit the target field entirely if 'docx' is correct — null is safe.","Use the type guard above during plugin discovery to filter bad manifests early."],"tags":["plugin","manifest","config","validation","openxml"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}