iOfficeAI/OfficeCLI · error · CliException
plugin_error
plugin_error
Error message
Format-handler plugin '{_plugin.Manifest.Name}' reported error on {command ?? msgType}: {msg} What it means
Thrown when the plugin sends a well-formed error envelope: {"msg_type":"error","error":{"code":"...","message":"..."}}. This is the normal error-reporting channel — the plugin intentionally declined or failed the operation. The CliException's Code is set from the plugin's error.code field (defaulting to plugin_error), and the message field carries the plugin's human-readable explanation.
Source
Thrown at src/officecli/Core/Plugins/FormatHandlerSession.cs:257
}
if (reply is null)
{
_broken = true;
throw new CliException(
$"Format-handler plugin '{_plugin.Manifest.Name}' reply is not a JSON object. First chars: \"{Truncate(line, 80)}\".")
{ Code = "protocol_mismatch" };
}
var replyType = reply["msg_type"]?.GetValue<string>() ?? "";
if (replyType == "ok")
return reply["result"];
if (replyType == "error")
{
var err = reply["error"]?.AsObject();
var code = err?["code"]?.GetValue<string>() ?? "plugin_error";
var msg = err?["message"]?.GetValue<string>() ?? "(no message)";
throw new CliException(
$"Format-handler plugin '{_plugin.Manifest.Name}' reported error on {command ?? msgType}: {msg}")
{ Code = code };
}
_broken = true;
throw new CliException(
$"Format-handler plugin '{_plugin.Manifest.Name}' replied with unknown msg_type '{replyType}'.")
{ Code = "protocol_mismatch" };
}
catch (IOException ex)
{
_broken = true;
throw new CliException(
$"Format-handler plugin '{_plugin.Manifest.Name}' stdin/stdout I/O failed: {ex.Message}", ex)
{ Code = "plugin_stream_closed" };
}
}
}
View on GitHub (pinned to 1ced45e900)
Solutions
- Read the CliException Message — it contains the plugin's explanation after the colon.
- Read the CliException Code — it carries the plugin's error.code, which may be more specific than plugin_error (e.g. file_corrupt, missing_dependency).
- Fix the root cause the plugin describes: repair the input file, install the dependency, correct the argument.
- Unlike protocol_mismatch errors, the session is still usable — you can send the next command without restarting.
Example fix
// before: caller treats all plugin errors as fatal
try { session.Send("save", null, args, props); }
catch (CliException) { session.Dispose(); throw; } // overkill for plugin_error
// after: only restart on broken-session codes
try { session.Send("save", null, args, props); }
catch (CliException ex) {
if (session.IsBroken) { session.Dispose(); throw; }
// plugin_error is recoverable — log and continue or surface to user
Console.Error.WriteLine($"Plugin reported: {ex.Message} [{ex.Code}]");
} Defensive patterns
Strategy: try-catch
Try / catch
try
{
var result = session.Send(msgType, command, args, props);
}
catch (CliException ex) when (ex.Code != null && ex.Code != "plugin_error" && !session.IsBroken)
{
// Only protocol-level failures poison the session.
// A plugin_error means the plugin intentionally declined — session is still usable.
throw;
}
// For plugin_error specifically:
catch (CliException ex) when (ex.Code == "plugin_error" || !session.IsBroken)
{
// Recoverable: log the message, surface to user, or fall back.
Console.Error.WriteLine($"Plugin declined: {ex.Message} [{ex.Code}]");
} Prevention
- Read the CliException.Code — it carries the plugin's error.code, which is more specific than 'plugin_error'.
- Distinguish recoverable plugin_error from session-poisoning protocol_mismatch/plugin_stream_closed.
- Do NOT dispose the session on plugin_error — it's still healthy for the next command.
- Validate command inputs before sending to avoid predictable plugin rejections.
When it happens
Trigger: FormatHandlerSession.SendRaw reads a reply where reply["msg_type"] == "error". The code is extracted from reply["error"]["code"] (or "plugin_error" if absent); the message from reply["error"]["message"] (or "(no message)"). The session is NOT marked _broken — this is a recoverable per-command error, not a protocol failure.
Common situations: Plugin can't open a corrupted file and reports an error. Plugin encounters an unsupported feature in the target format. Plugin's external dependency (LibreOffice, a native library) is missing. Plugin rejects an invalid command argument. The error.code propagates as the CliException Code, so downstream error handling can branch on it.
Related errors
- protocol_mismatch
- corrupt_batch
- Unsupported file type: {ext}. Supported: .docx, .xlsx, .pptx
- plugin_create_failed
- corrupt_batch
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/21163f9059b78306.
Report an issue: GitHub.