iOfficeAI/OfficeCLI · error · CliException

invalid_json

invalid_json

Error message

Invalid JSON data: parsed to null

What it means

Thrown by TemplateMerger.ParseMergeData when JsonNode.Parse returns null. System.Text.Json returns null only for the literal JSON token 'null' (a file containing just 'null', or the argument string 'null'). The merge needs a JSON object to map placeholders, so a null root is unusable and surfaced as code invalid_json.

Source

Thrown at src/officecli/Core/TemplateMerger.cs:53

    /// <summary>
    /// Parse merge data from a string argument. If the value ends with .json and the file exists,
    /// read from file; otherwise parse as inline JSON.
    /// </summary>
    public static Dictionary<string, string> ParseMergeData(string dataArg)
    {
        string jsonText;

        if (dataArg.EndsWith(".json", StringComparison.OrdinalIgnoreCase) && File.Exists(dataArg))
        {
            jsonText = File.ReadAllText(dataArg);
        }
        else
        {
            jsonText = dataArg;
        }

        var jsonNode = JsonNode.Parse(jsonText)
            ?? throw new CliException("Invalid JSON data: parsed to null")
            {
                Code = "invalid_json",
                Suggestion = "Provide valid JSON object, e.g. '{\"name\":\"Alice\"}'"
            };

        if (jsonNode is not JsonObject jsonObj)
            throw new CliException("JSON data must be an object (not array or primitive)")
            {
                Code = "invalid_json",
                Suggestion = "Provide a JSON object, e.g. '{\"name\":\"Alice\"}'"
            };

        var data = new Dictionary<string, string>();
        // Pass 1: literal top-level keys win. {{a.b}} with data {"a.b":"X"}
        // resolves to "X" regardless of whether {"a":{"b":...}} also exists.
        // CONSISTENCY(merge-literal-key-precedence): mirrors the hyphen-key
        // contract (R21) — literal lookup is the canonical path; nested
        // dot-path flattening is a convenience layered on top, not a

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Provide a JSON object with your placeholder keys, e.g. '{"name":"Alice"}'.
  2. If the .json file is empty or contains 'null', populate it with an object.
  3. If you intended 'no substitutions', pass an empty object '{}' rather than null.

Example fix

// before
--data "null"            // parsed to null
// or file data.json contains: null
// after
--data '{"name":"Alice"}'
// data.json: {"name":"Alice"}
Defensive patterns

Strategy: validation

Validate before calling

// Reject the degenerate 'null' token before merging
var trimmed = dataArg.Trim();
if (trimmed == "null" || trimmed.Length == 0)
    throw new InvalidOperationException("merge data must be a JSON object, got null/empty");

Try / catch

try { data = TemplateMerger.ParseMergeData(dataArg); }
catch (CliException ex) when (ex.Code == "invalid_json")
{ /* show suggestion: provide a JSON object like {"name":"Alice"} */ }

Prevention

When it happens

Trigger: Passing the data argument as the literal string 'null'; a .json file whose entire content is the four bytes 'null'; an upstream layer that serialized a null reference to the JSON token null.

Common situations: A data file that was never populated (serialized null); an agent passing through a null JSON value; passing the word null meaning 'no data'.

Understand the failure class

Related errors


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