iOfficeAI/OfficeCLI · error · CliException

plugin_spawn_failed

plugin_spawn_failed

Error message

Failed to start format-handler plugin '{_plugin.Manifest.Name}'.

What it means

CliException (code 'plugin_spawn_failed') thrown when Process.Start returns null for a format-handler plugin. PSI is configured with UTF-8 no-BOM on all three streams and injects OFFICECLI_BIN from Environment.ProcessPath. Process.Start returning null is rare on modern runtimes (it usually throws on failure).

Source

Thrown at src/officecli/Core/Plugins/FormatHandlerSession.cs:87

            ArgumentList = { "open", _filePath },
            UseShellExecute = false,
            RedirectStandardInput = true,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = true,
            // Force UTF-8 no-BOM on all three streams. Windows defaults to
            // Console.InputEncoding/OutputEncoding which can be GBK/CP1252
            // depending on locale — wire format must be locale-independent.
            StandardInputEncoding = utf8NoBom,
            StandardOutputEncoding = utf8NoBom,
            StandardErrorEncoding = utf8NoBom,
        };
        var selfPath = Environment.ProcessPath;
        if (!string.IsNullOrEmpty(selfPath))
            psi.Environment["OFFICECLI_BIN"] = selfPath;

        _proc = Process.Start(psi)
            ?? throw new CliException($"Failed to start format-handler plugin '{_plugin.Manifest.Name}'.")
                { Code = "plugin_spawn_failed" };

        // Wrap stdin with an explicit UTF-8 no-BOM writer on the base
        // stream. Process.StandardInput's default StreamWriter buffers
        // independently and (on some runtimes) ignores AutoFlush — going
        // direct to BaseStream avoids the surprise.
        _stdinWriter = new StreamWriter(_proc.StandardInput.BaseStream, utf8NoBom, bufferSize: 8192, leaveOpen: true)
        {
            AutoFlush = true,
            NewLine = "\n",
        };
        _stdoutReader = _proc.StandardOutput;
        Volatile.Write(ref _lastActivityTicks, DateTime.UtcNow.Ticks);

        // Background stderr pump: heartbeat lines (`{"heartbeat":true}`)
        // reset the activity timer; everything else is diagnostic noise we
        // drain to keep the OS pipe buffer from filling and blocking the
        // plugin. We intentionally do not surface the diagnostic text here

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Verify plugin.ExecutablePath exists and is executable (chmod +x on Unix).
  2. Re-register or reinstall the plugin to refresh the executable path.
  3. Check antivirus/EDR is not blocking the spawn; capture Process.Start's inner exception if any.
Defensive patterns

Strategy: validation

Validate before calling

if (!File.Exists(plugin.ExecutablePath))
    throw new InvalidOperationException($"Plugin executable missing: {plugin.ExecutablePath}");
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
    File.SetUnixPermissionOrThrow(plugin.ExecutablePath, UnixFileMode.UserExecute);

Try / catch

try { session = new FormatHandlerSession(plugin); }
catch (CliException ex) when (ex.Code == "plugin_spawn_failed")
{ /* verify executable path/permissions; reinstall plugin */ }

Prevention

When it happens

Trigger: Spawning the format-handler plugin's executable path returned null — most commonly the path does not exist, is not executable, or the runtime could not create the process handle.

Common situations: Plugin executable moved/uninstalled after registration; execute permission missing on Linux/macOS; path with spaces or non-ASCII mishandled in manifest; antivirus blocking process creation on Windows.

Related errors


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