iOfficeAI/OfficeCLI · error · CliException
protocol_mismatch
protocol_mismatch
Error message
Format-handler add-part returned null.
What it means
CliException (code 'protocol_mismatch') thrown when the format-handler's reply to an 'add_part' command is null after AsObject() — the session returned no payload. The reply is then read for rel_id and part_path (both default to empty string if absent).
Source
Thrown at src/officecli/Core/Plugins/FormatHandlerProxy.cs:182
["part_path"] = partPath,
["xpath"] = xpath,
["action"] = action,
};
if (xml is not null) args["xml"] = xml;
_session.Send("command", "raw_set", args);
}
public (string RelId, string PartPath) AddPart(string parentPartPath, string partType, Dictionary<string, string>? properties = null)
{
var args = new JsonObject
{
["parent_part_path"] = parentPartPath,
["part_type"] = partType,
};
var props = properties is not null ? PropsToJson(properties) : null;
var result = _session.Send("command", "add_part", args, props)?.AsObject();
if (result is null)
throw new CliException("Format-handler add-part returned null.") { Code = "protocol_mismatch" };
var relId = result["rel_id"]?.GetValue<string>() ?? "";
var partPath = result["part_path"]?.GetValue<string>() ?? "";
return (relId, partPath);
}
// ----- Format-specific view extensions ------------------------------
//
// These are NOT on IDocumentHandler — they're entry points used by main's
// CommandBuilder.View when a built-in handler (Word/Excel/PPT) declines.
// `view html` and `view forms` historically downcast to a concrete handler;
// now `else if (handler is FormatHandlerProxy proxy) ...` provides the
// plugin-side fallback. Each method maps onto the corresponding `view`
// command with a mode key the plugin chooses how to render.
/// <summary>
/// Request SVG preview from the plugin (`view mode=svg`). Returns null
/// if the plugin replies with <c>unsupported_command</c>.
/// </summary>View on GitHub (pinned to 1ced45e900)
Solutions
- Verify the plugin implements the add_part command (see capability declaration / commands list).
- Update the plugin to return {"rel_id":"...","part_path":"..."} for add_part replies.
- Upgrade plugin and host to the same protocol version (§5.3).
Defensive patterns
Strategy: try-catch
Validate before calling
// Confirm the plugin declares add_part before calling.
var caps = session.Capabilities;
if (caps?.Commands is { Count: > 0 } c && !c.Contains("add_part"))
throw new InvalidOperationException("Plugin does not implement add_part."); Try / catch
try { proxy.AddPart(parent, type, props); }
catch (CliException ex) when (ex.Code == "protocol_mismatch" && ex.Message.Contains("add-part returned null"))
{ /* plugin did not return rel_id/part_path; rebuild/upgrade it */ } Prevention
- Gate add_part calls on the plugin's declared Commands capability.
- Pin plugin and host protocol versions together.
- Add integration tests asserting add_part returns a non-null object.
When it happens
Trigger: Calling FormatHandlerProxy.AddPart sends a 'command/add_part' envelope; the plugin replies with a null result (ack-only, or empty object that the session normalized to null).
Common situations: Plugin does not implement add_part and replies with an empty ack; plugin crashed mid-handling; protocol drift where add_part semantics changed and the plugin emits a different envelope.
Related errors
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/24e01c5f4d8c6f9f.
Report an issue: GitHub.