{"record":{"id":"24e01c5f4d8c6f9f","repo":"iOfficeAI/OfficeCLI","slug":"protocol-mismatch","errorCode":"protocol_mismatch","errorMessage":"Format-handler add-part returned null.","messagePattern":"Format-handler add-part returned null\\.","errorType":"exception","errorClass":"CliException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/Plugins/FormatHandlerProxy.cs","lineNumber":182,"sourceCode":"            [\"part_path\"] = partPath,\n            [\"xpath\"] = xpath,\n            [\"action\"] = action,\n        };\n        if (xml is not null) args[\"xml\"] = xml;\n        _session.Send(\"command\", \"raw_set\", args);\n    }\n\n    public (string RelId, string PartPath) AddPart(string parentPartPath, string partType, Dictionary<string, string>? properties = null)\n    {\n        var args = new JsonObject\n        {\n            [\"parent_part_path\"] = parentPartPath,\n            [\"part_type\"] = partType,\n        };\n        var props = properties is not null ? PropsToJson(properties) : null;\n        var result = _session.Send(\"command\", \"add_part\", args, props)?.AsObject();\n        if (result is null)\n            throw new CliException(\"Format-handler add-part returned null.\") { Code = \"protocol_mismatch\" };\n        var relId = result[\"rel_id\"]?.GetValue<string>() ?? \"\";\n        var partPath = result[\"part_path\"]?.GetValue<string>() ?? \"\";\n        return (relId, partPath);\n    }\n\n    // ----- Format-specific view extensions ------------------------------\n    //\n    // These are NOT on IDocumentHandler — they're entry points used by main's\n    // CommandBuilder.View when a built-in handler (Word/Excel/PPT) declines.\n    // `view html` and `view forms` historically downcast to a concrete handler;\n    // now `else if (handler is FormatHandlerProxy proxy) ...` provides the\n    // plugin-side fallback. Each method maps onto the corresponding `view`\n    // command with a mode key the plugin chooses how to render.\n\n    /// <summary>\n    /// Request SVG preview from the plugin (`view mode=svg`). Returns null\n    /// if the plugin replies with <c>unsupported_command</c>.\n    /// </summary>","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Plugins/FormatHandlerProxy.cs#L164-L200","documentation":"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).","triggerScenarios":"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).","commonSituations":"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.","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)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Confirm the plugin declares add_part before calling.\nvar caps = session.Capabilities;\nif (caps?.Commands is { Count: > 0 } c && !c.Contains(\"add_part\"))\n    throw new InvalidOperationException(\"Plugin does not implement add_part.\");","typeGuard":null,"tryCatchPattern":"try { proxy.AddPart(parent, type, props); }\ncatch (CliException ex) when (ex.Code == \"protocol_mismatch\" && ex.Message.Contains(\"add-part returned null\"))\n{ /* plugin did not return rel_id/part_path; rebuild/upgrade it */ }","preventionTips":["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."],"tags":["plugins","format-handler","protocol","cli-exception"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}