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

  1. Verify the plugin implements the add_part command (see capability declaration / commands list).
  2. Update the plugin to return {"rel_id":"...","part_path":"..."} for add_part replies.
  3. 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

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.