iOfficeAI/OfficeCLI · error · ArgumentException

send: empty item

Error message

send: empty item

What it means

ExecuteSend deserializes a single batch-item JSON string into a BatchItem object. If deserialization returns null (the JSON was empty, whitespace-only, or a JSON null literal), the coalescing ?? operator throws ArgumentException. This mirrors the SDK send(item) contract: a null/empty item is a caller bug, not a batch-level failure. Unlike ExecuteBatch, the failure throws (not captured per-item) to match the standalone command's exit contract.

Source

Thrown at src/officecli/Core/BatchExecutor.cs:86

    /// <summary>
    /// Mirrors the SDKs' <c>send(item)</c> (as distinct from <c>batch(items)</c>):
    /// runs ONE batch-shaped item and returns EXACTLY what the CLI single command
    /// writes to stdout — with <paramref name="json"/> the standalone command's
    /// envelope (WrapEnvelopeText's `{success,data,message}` for text commands
    /// like set/add/remove, WrapEnvelope's `{success,data}` for data commands like
    /// get/query), without it the plain text. A failure throws instead of being
    /// captured per-item, matching the standalone command's exit contract.
    /// </summary>
    /// <param name="itemJson">A single batch item object — the same shape as one
    /// entry in <see cref="ExecuteBatch"/>'s array, or the SDKs' `send(item)` argument.</param>
    /// <param name="json">Mirrors the CLI `--json` toggle: structured envelope vs plain text.</param>
    public static string ExecuteSend(IDocumentHandler handler, string itemJson, bool json)
    {
        try
        {
            var item = JsonSerializer.Deserialize(itemJson, BatchJsonContext.Default.BatchItem)
                ?? throw new ArgumentException("send: empty item");
            var inner = CommandBuilder.ExecuteBatchItem(handler, item, json);
            if (!json) return inner;

            // Match the standalone command's envelope by inner shape — a JSON payload
            // (get/query/view/validate/…) wraps with WrapEnvelope; a plain-text
            // message (set/add/remove/…) wraps with WrapEnvelopeText (which adds the
            // `message` field the CLI emits). Content-based so a new command inherits
            // the right envelope without a hand-kept command→envelope map.
            var trimmed = inner.TrimStart();
            return trimmed.StartsWith('{') || trimmed.StartsWith('[')
                ? OutputFormatter.WrapEnvelope(inner)
                : OutputFormatter.WrapEnvelopeText(inner);
        }
        catch (Exception ex)
        {
            return RenderTopLevelError(ex, json);
        }
    }

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Ensure itemJson is a valid BatchItem JSON object before calling ExecuteSend — check for null/empty/whitespace.
  2. Guard at the caller boundary: if (string.IsNullOrWhiteSpace(itemJson)) throw with a descriptive message.
  3. Verify the JSON is not the literal "null" — JsonSerialializer.Deserialize returns null for JSON null.

Example fix

// before
var result = BatchExecutor.ExecuteSend(handler, itemJson, json);
// after
if (string.IsNullOrWhiteSpace(itemJson) || itemJson.Trim() == "null")
    throw new ArgumentException("itemJson must be a non-empty batch item JSON object.");
var result = BatchExecutor.ExecuteSend(handler, itemJson, json);
Defensive patterns

Strategy: validation

Validate before calling

static void ValidateItemJson(string itemJson)
{
    if (string.IsNullOrWhiteSpace(itemJson))
        throw new ArgumentException("itemJson must be a non-empty JSON object.");
    var trimmed = itemJson.Trim();
    if (trimmed == "null")
        throw new ArgumentException("itemJson is JSON null — provide a batch item object.");
}

// Usage:
ValidateItemJson(itemJson);
var result = BatchExecutor.ExecuteSend(handler, itemJson, json);

Try / catch

try { var result = BatchExecutor.ExecuteSend(handler, itemJson, json); }
catch (ArgumentException ex) when (ex.Message == "send: empty item")
{
    // The caller passed null/empty/whitespace/"null" JSON
    throw new ArgumentException("Batch item was empty. Provide a valid JSON item object.", ex);
}

Prevention

When it happens

Trigger: Calling BatchExecutor.ExecuteSend with an empty string, "null", whitespace, or a JSON literal that deserializes to null. Common in SDK send(item) wrappers that forward user-supplied input without checking for emptiness.

Common situations: An SDK wrapper passes a default/empty string when the user provides no item. A serialization bug produces 'null' or '' instead of a valid item JSON. A network layer sends an empty body after stripping content.

Related errors


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