iOfficeAI/OfficeCLI · warning · JsonException
Expected "key=value" string in props array
Error message
Expected "key=value" string in props array
What it means
JsonException from LenientStringDictionaryConverter.Read while parsing a `props` value given as an array (the ["key=value", ...] form). Each element must be a JSON string; this throws when an element is a number, boolean, object, or nested array. It mirrors McpServer.ParseProps, which only accepts string kv-pairs in the array form.
Source
Thrown at src/officecli/BatchTypes.cs:28
{
public override Dictionary<string, string>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Null) return null;
var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
// Array form: ["key=value", ...]. This mirrors the single-command MCP
// `props` argument and the CLI `--prop key=value` flag, so an agent that
// learned props from `set`/`add` produces the same shape inside a batch
// item. Before this, batch props was object-only and every array-form
// batch failed with "Expected object for props" — observed as a 100%
// batch-failure for models that (correctly) reused the single-command
// props shape. Lenient split on the first '=' matches McpServer.ParseProps.
if (reader.TokenType == JsonTokenType.StartArray)
{
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray) return dict;
if (reader.TokenType != JsonTokenType.String)
throw new JsonException("Expected \"key=value\" string in props array");
var kv = reader.GetString()!;
var eq = kv.IndexOf('=');
if (eq > 0) dict[kv[..eq]] = kv[(eq + 1)..]; // skip malformed, as ParseProps does
}
throw new JsonException("Unexpected end of JSON");
}
if (reader.TokenType != JsonTokenType.StartObject)
throw new JsonException("Expected object or [\"key=value\"] array for props");
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject) return dict;
if (reader.TokenType != JsonTokenType.PropertyName)
throw new JsonException("Expected property name");
var key = reader.GetString()!;
reader.Read();
var value = reader.TokenType switch
{
JsonTokenType.String => reader.GetString()!,View on GitHub (pinned to 1ced45e900)
Solutions
- Make every props-array element a "key=value" string: props: ["text=hi", "count=42"].
- If you have rich values, switch to the object form: props: { text: 'hi', count: '42' }.
- Validate/normalize props to strings before serializing the batch.
Example fix
// before: { command:'set', props: ['text=hi', 42] }
// after: { command:'set', props: ['text=hi', 'count=42'] } // or props: { text:'hi', count:'42' } Defensive patterns
Strategy: validation
Validate before calling
// Normalize props to the accepted shapes before serializing a batch
function normalizeProps(props) {
if (props == null) return undefined;
if (Array.isArray(props)) return props.map(v => typeof v === 'string' ? v : null).filter(Boolean); // drop non-strings
if (typeof props === 'object') return props;
return undefined;
} Type guard
// Accept only string elements in a props array
function isStringArray(a) { return Array.isArray(a) && a.every(x => typeof x === 'string'); } Prevention
- Always quote props-array values as "key=value" strings.
- Prefer the object form {key:'value'} unless you specifically need the array form.
- Coerce numbers to strings before pushing into a props array.
When it happens
Trigger: A batch item with "props": ["text=hi", 42] or "props": ["text=hi", {"x":1}] or "props": [true]. Any non-string token inside the props array.
Common situations: An agent/model that emits props as a mixed array after learning a numeric value; serializing a Map/struct directly into the array; hand-built JSON with an unquoted value.
Related errors
- Expected object or ["key=value"] array for props
- Unexpected token {reader.TokenType} for prop value '{key}'
- Unexpected end of JSON
- Expected property name
- Expected StartObject for BatchItem
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/7790258cc6963b02.
Report an issue: GitHub.