{"record":{"id":"5699b5c72f03805a","repo":"iOfficeAI/OfficeCLI","slug":"plugin-create-failed","errorCode":"plugin_create_failed","errorMessage":"Format-handler plugin '{plugin.Manifest.Name}' timed out creating {path} (60s).","messagePattern":"Format-handler plugin '(.+?)' timed out creating (.+?) \\(60s\\)\\.","errorType":"error_code","errorClass":"CliException","httpStatus":null,"severity":"error","filePath":"src/officecli/BlankDocCreator.cs","lineNumber":71,"sourceCode":"            RedirectStandardError = true,\n            // CONSISTENCY(child-stream-encoding): pin UTF-8 on every redirected\n            // child stream. Unset, .NET decodes with the console's code page,\n            // which is the host's default (CP936/CP437) — officecli no longer\n            // switches the console to 65001 for redirected runs, so a plugin's\n            // non-ASCII diagnostics would decode wrong.\n            StandardErrorEncoding = System.Text.Encoding.UTF8,\n            CreateNoWindow = true,\n        };\n        using var proc = System.Diagnostics.Process.Start(psi);\n        if (proc is null) return false;\n        // Bound the wait: a hung plugin previously blocked `create` forever\n        // (stderr is the only redirected stream, so the read itself cannot\n        // deadlock, but WaitForExit had no timeout or Kill).\n        var stderrTask = proc.StandardError.ReadToEndAsync();\n        if (!proc.WaitForExit(60_000))\n        {\n            try { proc.Kill(true); } catch { }\n            throw new OfficeCli.Core.CliException(\n                $\"Format-handler plugin '{plugin.Manifest.Name}' timed out creating {path} (60s).\")\n            { Code = \"plugin_create_failed\" };\n        }\n        var stderr = stderrTask.Result;\n        if (proc.ExitCode != 0)\n        {\n            // Treat unknown-subcommand exit-64 as \"plugin doesn't implement\n            // create\" — fall back to NotSupportedException so the user sees\n            // the same error they'd see without any plugin installed.\n            if (proc.ExitCode == 64) return false;\n            throw new OfficeCli.Core.CliException(\n                $\"Format-handler plugin '{plugin.Manifest.Name}' failed to create {path}: {stderr.Trim()}\")\n            { Code = \"plugin_create_failed\" };\n        }\n        return true;\n    }\n\n    private static void CreateExcel(string path, string? locale = null)","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/BlankDocCreator.cs#L53-L89","documentation":"Thrown when a format-handler plugin process started by TryCreateViaPlugin does not exit within the 60-second WaitForExit timeout. The process is killed (proc.Kill(true)) and a CliException with code `plugin_create_failed` is raised. It guards against a hung plugin blocking the `create` command indefinitely.","triggerScenarios":"`officecli create data.xlsx` (or any extension) where the registered plugin's `create` subcommand deadlocks, loops infinitely, or blocks on a prompt/lock with no input. Also if the plugin waits on a network resource that never responds, or holds an exclusive file lock that itself waits.","commonSituations":"A plugin executable prompts for input under non-interactive use; a plugin has an unbounded retry loop; the plugin binary is misconfigured and spins; a plugin depends on a license server that is unreachable; the target path is on a slow/network mount causing the plugin to stall past 60s.","solutions":["Run the plugin's create subcommand directly in a shell to reproduce the hang: `<plugin-exe> create <path>` and observe where it blocks.","Check the plugin for interactive prompts, infinite loops, or missing input; ensure it is non-interactive when invoked from OfficeCLI.","If 60s is genuinely too short for a legitimate large operation, split the work or pre-generate the file outside the plugin.","File a bug against the plugin with the reproduction; the timeout is a safety bound, not a tunable in OfficeCLI."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// No pre-call validation can predict a plugin hang; run create through a wrapper that owns the timeout.\n// Pre-check the plugin is non-interactive: run `<plugin> create --help` once and fail fast if it prompts.","typeGuard":"// Guard: does a plugin exist and is it reachable for this extension before relying on it?\nstatic bool PluginCanCreate(string ext) =>\n    OfficeCli.Core.Plugins.PluginRegistry.FindFor(\n        OfficeCli.Core.Plugins.PluginKind.FormatHandler, ext) is not null;","tryCatchPattern":"// Catch the timeout specifically so a fallback (built-in create / different plugin) can run.\ntry { BlankDocCreator.Create(path); }\ncatch (OfficeCli.Core.CliException ex) when (ex.Code == \"plugin_create_failed\")\n{\n    // log ex.Message, then fall back to a built-in format or surface to the user\n    Log.PluginCreateFailed(ex.Message);\n    throw;\n}","preventionTips":["Smoke-test each plugin's `create` subcommand in isolation before deploying it under OfficeCLI.","Ensure plugin executables are non-interactive when stdout/stdin are not a TTY.","Avoid plugins that hold exclusive locks or wait on network resources during create."],"tags":["plugin","timeout","create","process"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}